태스크 동시성 제한이 AWS HealthOmics 워크플로우 실행의 스토리지 비용을 증가시키는 원리
AWS HealthOmics에서 유전체 워크플로우를 실행할 때, 비용 관리나 팀 간 용량 공유를 위해 Run Group의 maxCpus로 태스크 동시성을 제어할 수 있습니다. 하지만 여기에는 중요한 부작용이 있습니다: 동시성을 제한하면 오히려 총 실행 비용이 증가할 수 있으며, 특히 스토리지 요금에서 그 영향이 나타납니다.
이 효과를 측정하고 과금 메커니즘을 검증하기 위해 통제된 실험을 수행했습니다.
요약 (TL;DR)
- 50개 태스크 워크플로우의 동시성을 완전 병렬에서 2개 동시 실행으로 제한하면 실행 시간이 5.67배 증가
- 스토리지 비용이 5.67배 증가 ($0.049 → $0.278), 실행 시간과 정확히 비례
- 컴퓨팅 비용은 거의 동일 ($0.220 → $0.217, -1.2%)
- 총 비용이 84% 증가 ($0.269 → $0.496)
배경: HealthOmics 과금 방식
HealthOmics 실행 비용은 근본적으로 다른 과금 모델을 가진 두 가지 독립적인 구성 요소로 이루어져 있습니다:
컴퓨팅 비용 (태스크 단위)
각 태스크는 할당된 인스턴스 유형의 초당 요금으로, 실제 실행 시간(시작~종료) 기준으로 과금됩니다(최소 60초). 태스크가 병렬로 실행되든 순차적으로 실행되든, 각 태스크의 실행 시간은 동일하므로 총 컴퓨팅 비용은 동시성과 무관하게 동일합니다.
컴퓨팅_비용 = Σ max(태스크_실행_시간(초), 60) × 인스턴스_초당_요금
스토리지 비용 (실행 단위)
실행 스토리지는 실행이 "Running" 상태에 진입할 때 프로비저닝되며, "Stopping"으로 전환될 때까지 유지됩니다. STATIC 스토리지의 경우, 전체 프로비저닝된 용량(최소 1,200 GiB)에 대해 전체 벽시계 시간(wall-clock duration) 동안 비용을 지불합니다:
스토리지_비용 = $0.0001918/GB-시간 × 프로비저닝된_GiB × 실행_시간(시간)
즉, 실행 시간을 연장하는 모든 요인 — 동시성 제한 포함 — 이 스토리지 비용을 직접적으로 증가시킵니다.
실험 설계
워크플로우
50개의 scatter 태스크를 가진 커스텀 WDL 워크플로우를 작성했습니다. 각 태스크는:
- 2 CPU, 4 GB 메모리 요청 (
omics.c.large에 매핑) - 100 MB 랜덤 파일 생성 (스토리지 I/O 시뮬레이션)
- ~120초의 CPU 집약적 작업 수행 (
md5sum체크섬)
마지막 AggregateResults 태스크가 모든 출력을 수집합니다.
version 1.0
workflow ScatterStorageCostTest {
input {
Int num_tasks = 50
Int task_duration_seconds = 120
Int file_size_mb = 100
}
scatter (i in range(num_tasks)) {
call ComputeTask {
input:
task_id = i,
duration_seconds = task_duration_seconds,
file_size_mb = file_size_mb
}
}
call AggregateResults {
input:
results = ComputeTask.result_file
}
output {
File final_report = AggregateResults.report
}
}
task ComputeTask {
input {
Int task_id
Int duration_seconds
Int file_size_mb
}
command <<<
echo "Task ~{task_id} starting at $(date -u +%Y-%m-%dT%H:%M:%SZ)"
dd if=/dev/urandom of=output_~{task_id}.bin bs=1M count=~{file_size_mb} 2>/dev/null
end_time=$((SECONDS + ~{duration_seconds}))
while [ $SECONDS -lt $end_time ]; do
md5sum output_~{task_id}.bin > /dev/null 2>&1
done
echo "Task ~{task_id} completed at $(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "task_~{task_id}: duration=~{duration_seconds}s, file_size=~{file_size_mb}MB" > result_~{task_id}.txt
>>>
runtime {
docker: "<ecr-uri>/ubuntu:20.04"
cpu: 2
memory: "4 GB"
}
output {
File result_file = "result_~{task_id}.txt"
}
}
task AggregateResults {
input {
Array[File] results
}
command <<<
echo "=== Scatter Storage Cost Test Results ==="
echo "Aggregation started at $(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "Number of tasks: $(ls ~{sep=' ' results} | wc -w)"
echo ""
cat ~{sep=' ' results}
echo ""
echo "Aggregation completed at $(date -u +%Y-%m-%dT%H:%M:%SZ)"
>>>
runtime {
docker: "<ecr-uri>/ubuntu:20.04"
cpu: 1
memory: "2 GB"
}
output {
File report = stdout()
}
}
두 번의 실행, 하나의 변수
동시성 제약만 다르게 하여 동일한 워크플로우를 두 번 실행했습니다:
| 파라미터 | Run A (높은 동시성) | Run B (낮은 동시성) |
|---|---|---|
| Run Group | 없음 (기본 제한) | maxCpus=4 |
| 실효 병렬도 | ~50개 태스크 (전부 동시) | 2개 태스크씩 |
| 스토리지 유형 | STATIC (1,200 GiB) | STATIC (1,200 GiB) |
| 워크플로우 및 파라미터 | 동일 | 동일 |
| 리전 | us-east-1 | us-east-1 |
maxCpus=4이고 각 태스크가 2 CPU를 요청하므로, Run B는 동시에 2개 태스크만 실행할 수 있었습니다. 두 실행은 10초 이내 간격으로 시작되었습니다.
결과
실행 시간
| Run A (높은 동시성) | Run B (낮은 동시성) | 비율 | |
|---|---|---|---|
| 총 실행 시간 | 12분 48초 (768.6초) | 1시간 12분 35초 (4,355.0초) | 5.67배 |
비용 분석
| 비용 항목 | Run A (높은 동시성) | Run B (낮은 동시성) | 비율 |
|---|---|---|---|
| 컴퓨팅 비용 | $0.2198 | $0.2171 | 0.99배 (-1.2%) |
| 스토리지 비용 | $0.0491 | $0.2784 | 5.67배 (+467%) |
| 총 비용 | $0.2690 | $0.4955 | 1.84배 (+84%) |
총 비용 대비 스토리지 비율
| Run A (높은 동시성) | Run B (낮은 동시성) | |
|---|---|---|
| 스토리지 | 18.3% | 56.2% |
| 컴퓨팅 | 81.7% | 43.8% |
낮은 동시성에서 스토리지가 지배적인 비용 항목이 되었습니다 — 총 비용의 1/5 미만에서 절반 이상으로 역전되었습니다.
수학적 검증
실행 매니페스트의 실제 태스크 시작/종료 타임스탬프를 사용하여 보고된 비용을 과금 공식과 대조 검증했습니다.
컴퓨팅 비용 검증
각 ComputeTask (2 CPU, 4 GiB)는 omics.c.large 인스턴스에 매핑되며, 시간당 $0.1148 (초당 $0.00003188)입니다.
| Run A | Run B | |
|---|---|---|
| 총 태스크 수 | 51 | 51 |
| 총 과금 시간(초) | 6,893.7초 | 6,806.9초 |
| ComputeTask 평균 실행 시간 | 136.7초 | 134.9초 |
| 계산된 컴퓨팅 비용 | $0.2197 | $0.2170 |
| 보고된 컴퓨팅 비용 | $0.2198 | $0.2171 |
총 과금 시간의 차이는 두 실행 간 -1.3%에 불과합니다. Run B의 태스크가 동시 실행 태스크가 2개뿐이어서 리소스 경합이 줄어 약간 더 빠르게 실행되었지만(태스크당 ~1.8초 감소), 이 효과는 무시할 수 있는 수준입니다.
결론: 컴퓨팅 비용은 개별 태스크 실행 시간의 합에 의존하며, 전체 실행 시간과는 무관합니다. 병렬도는 이 합계를 변경하지 않습니다.
스토리지 비용 검증
스토리지 비용 = $0.0001918/GB-시간 × 1,200 GiB × 실행_시간(시간)
| Run A | Run B | |
|---|---|---|
| 실행 시간 | 768.6초 (0.2135시간) | 4,355.0초 (1.2097시간) |
| 계산된 스토리지 비용 | $0.0491 | $0.2784 |
| 보고된 스토리지 비용 | $0.0491 | $0.2784 |
센트 단위까지 정확히 일치합니다. 스토리지 비용은 벽시계 시간에 정확히 비례합니다.
사용된 요금 단가
| 항목 | 요금 | 출처 |
|---|---|---|
| omics.c.large (2 vCPU, 4 GiB) | $0.1148/시간 | omics.c.4xlarge ($0.9180/시간, 16 vCPU)에서 산출 |
| STATIC Run Storage | $0.0001918/GB-시간 | AWS HealthOmics 요금표 (us-east-1) |
| DYNAMIC Run Storage | $0.0004110/GB-시간 | AWS HealthOmics 요금표 (us-east-1) |
| 최소 태스크 과금 시간 | 60초 | AWS HealthOmics 요금표 |
태스크 실행 패턴
Run A: 모든 태스크 병렬 실행
50개의 ComputeTask 인스턴스가 ~70초 이내에 모두 시작되어 ~4분 이내에 완료되었습니다. AggregateResults 태스크가 즉시 이어서 실행되었습니다.
시간 (시작 후 분) 0 1 2 3 4 5 6 7
|----|----|----|----|----|----|----|
Task 00-49 [========================================] (50개 전부 병렬)
AggregateResults [==]
Run B: 2개씩 순차 배치 실행
태스크가 25개의 순차 배치로 실행되었으며, 각 배치는 ~2.5분 소요 (135초 실행 + ~20초 스케줄링 오버헤드). 전체 태스크 실행에 ~58분이 소요되었습니다.
시간 (시작 후 분) 0 5 10 15 20 ... 55 60 65
|----|----|----|----|---- ... |----|----|----|
배치 1 (T43,T39) [====]
배치 2 (T22,T35) [====]
배치 3 (T44,T49) [====]
...
배치 25 (T31) [====]
AggregateResults [=]
일반화된 공식
검증된 결과로부터 스토리지 비용 오버헤드에 대한 일반 모델을 도출할 수 있습니다:
시간당 스토리지 소진율 (STATIC 1,200 GiB):
$0.0001918/GB-시간 × 1,200 GiB = $0.2302/시간
스토리지 비용 배수 ≈ 제한된_실행시간 / 완전_동시성_실행시간
동시성 제한으로 인한 실행 시간 1시간 추가마다
~$0.23의 스토리지 비용이 추가됩니다.
실험에서의 실제 배수(5.67배)가 이론적 최대값(50 태스크 / 2 동시 = 25배)보다 작은 이유:
- Run A에서도 태스크가 시차를 두고 시작되면서 ~70초의 스케줄링 오버헤드 발생
- Run B에서 각 배치 사이에 ~20초의 스케줄링 간격 존재
- 이러한 오버헤드가 단순
N / C_max추정 대비 비율을 압축
권장 사항
-
충분한 동시성 여유를 확보하세요. Run Group의
maxCpus를 scatter 태스크가 직렬화되지 않을 만큼 충분히 높게 설정하세요. HealthOmics 기본 제한(동시 3,000 CPU, 실행당 동시 10개 태스크)은 일반적으로 적절하지만, 낮은maxCpus의 커스텀 Run Group은 이 문제를 유발할 수 있습니다. -
짧은 실행에는 DYNAMIC 스토리지를 고려하세요. 워크플로우가 2시간 이내에 완료된다면, DYNAMIC 스토리지($0.0004110/GB-시간)는 1,200 GiB의 프로비저닝된 용량 대신 실제 소비된 GB-시간만 과금하므로 스토리지 비용 영향을 줄일 수 있습니다.
-
실행 시간을 비용 신호로 모니터링하세요. 예상보다 긴 실행 시간은 동시성 제한을 나타낼 수 있습니다. 예상 대비 실제 실행 시간을 비교하면 스토리지 비용 인플레이션을 조기에 감지할 수 있습니다.
-
진단에 Run Analyzer를 활용하세요. HealthOmics Run Analyzer(aws-healthomics-tools에서 제공)는 스토리지 대 컴퓨팅 비율을 포함한 상세 비용 분석을 제공하여, 동시성 관련 비용 인플레이션을 쉽게 식별할 수 있습니다.
결론
이 실험은 태스크 동시성 제한이 실행 시간을 연장함으로써 HealthOmics 실행 스토리지 비용을 직접적으로 증가시키며, 컴퓨팅 비용은 일정하게 유지됨을 확인합니다. 스토리지 비용은 벽시계 시간에 선형적으로 비례합니다: 5.67배 긴 실행은 5.67배 높은 스토리지 비용과 84%의 총 비용 증가를 초래했습니다.
더 많은 태스크와 더 긴 실행 시간을 가진 프로덕션 유전체 워크플로우에서는 이 효과가 더욱 두드러집니다. 태스크 단위 컴퓨팅 과금과 실행 시간 단위 스토리지 과금이라는 두 가지 서로 다른 과금 모델을 이해하는 것이 HealthOmics 워크플로우 비용 최적화의 핵심입니다.
us-east-1 리전의 AWS HealthOmics에서 커스텀 WDL 워크플로우로 테스트되었습니다. 비용 분석은 HealthOmics Run Analyzer를 사용하여 수행되었습니다.
No comments to display
No comments to display