ShardedByS3Key는 인스턴스마다 다른 조각만 읽게 하고, FullyReplicated는 전부 복제한다.ml.p4d 인스턴스의 GPU는 초당 수 GB를 소화하는데 스토리지가 그 속도를 못 맞추면 비싼 가속기가 I/O를 기다리며 논다. 그래서 Specialty는 "어떤 데이터를 어디에, 어떤 포맷으로 두는가"를 비용·성능 트레이드오프로 묻는다.
거의 모든 SageMaker 학습 데이터는 S3에서 출발한다. 사실상 무한 용량에 11 nine 내구성을 제공하고, SageMaker가 네이티브로 읽기 때문이다. 핵심은 데이터를 S3에서 GPU까지 어떻게 흘려보내느냐인 입력 모드 선택이다.
| 입력 모드 | 동작 | 적합한 상황 | 대가 |
|---|---|---|---|
| File 모드 | 학습 전 전체 데이터를 인스턴스 디스크(EBS)로 복사 | 작은 데이터, 랜덤 접근 필요, 단순함 우선 | 시작 지연, EBS 용량 ≥ 데이터 크기 |
| Pipe 모드 | S3에서 스트리밍, 디스크에 안 담음 | 대용량, 순차 접근, 시작 지연 최소화 | 랜덤 접근·완전 셔플 어려움, 포맷 제약 |
| FastFile 모드 | 필요한 파일만 on-demand로 POSIX처럼 접근 | 대용량인데 일부만 읽거나 랜덤 접근 | 파일 단위 지연이 누적될 수 있음 |
[File 모드] ████ 전체 복사(수십 분) ████ ▶ 학습 시작 ────────▶
[Pipe 모드] ▶ 학습 시작 ─── 스트리밍으로 계속 공급 ─────────▶
[FastFile] ▶ 학습 시작 ─── 필요한 파일만 그때그때 가져옴 ──▶
└ time-to-first-batch: File ≫ FastFile ≈ Pipe
from sagemaker.inputs import TrainingInput
# Pipe 모드: 전체를 내려받지 않고 스트리밍 → 큰 데이터에서 시작이 빠름
train_input = TrainingInput(
s3_data="s3://my-lake/features/train/",
input_mode="Pipe", # File | Pipe | FastFile
distribution="ShardedByS3Key", # 여러 인스턴스에 데이터 분할
content_type="application/x-recordio-protobuf",
)
estimator.fit({"train": train_input})distribution="ShardedByS3Key" : 다중 인스턴스 분산 학습에서 각 인스턴스가 데이터의 다른 조각만 읽어 중복을 없앤다.distribution="FullyReplicated" : 모든 인스턴스가 전체를 받는다. 작은 데이터·검증셋에 적합하다.💡 개념: File 모드는 학습 시작 전 전체 복사가 끝나야 첫 스텝이 돈다. 수백 GB면 이 복사만 수십 분이고 비싼 GPU가 그동안 논다. Pipe 모드는 첫 배치가 도착하자마자 학습을 시작하므로 time-to-first-batch가 짧다. 단 Pipe는 순차 스트리밍이라 에폭마다 완전한 셔플이 어렵고, 알고리즘이 Pipe를 지원해야 한다. FastFile은 이 둘의 절충으로, 랜덤 접근을 지원하면서 전체 복사를 피한다.
⚠️ 함정: "Pipe가 항상 빠르다"는 단순화는 위험하다. 데이터가 작고 에폭마다 랜덤 셔플이 중요하면 File/FastFile이 더 낫다. 지문에서 데이터 크기 · 접근 패턴 · 포맷 세 단서를 모두 확인해야 한다.
S3는 객체 스토리지라 POSIX 파일 시스템처럼 디렉터리·랜덤 읽기를 빠르게 못 한다. 학습이 같은 데이터를 여러 에폭 반복하거나 많은 작은 파일에 랜덤 접근해야 하면 파일 시스템 스토리지가 유리하다.
| 스토리지 | 특성 | ML 적합 시나리오 | 주의 |
|---|---|---|---|
| S3 | 객체 스토리지, 사실상 무한, 저렴 | 데이터레이크 원본, 1회성 대용량 스트리밍 | POSIX 랜덤 접근이 느림 |
| EFS | 관리형 NFS, 다중 인스턴스 공유, 탄력 확장 | 노트북·여러 잡이 공유하는 중간 규모 데이터셋 | 처리량이 Lustre보다 낮음 |
| FSx for Lustre | 고성능 병렬 파일시스템, S3 연동 | 대규모 분산 학습, 반복 읽기, 고처리량 요구 | 추가 비용·설정, 단발성 학습엔 과함 |
FSx for Lustre의 킬러 기능은 S3 리포지토리 연동이다. S3 버킷을 백엔드로 두고 FSx가 고성능 캐시처럼 동작한다. 데이터는 S3에 두되(저렴·내구성), 학습 시엔 Lustre의 높은 처리량으로 읽는다.
영구 보관 고속 작업 공간 학습 노드
┌──────────────┐ 연동 ┌──────────────────┐ 마운트 ┌──────────┐
│ S3 버킷 │ ◀────▶ │ FSx for Lustre │ ◀──────▶│ ml.p4d × N│
│ (원본·저렴) │ │ (병렬 FS·저지연) │ └──────────┘
└──────────────┘ └──────────────────┘
from sagemaker.inputs import FileSystemInput
# FSx for Lustre를 학습 입력으로 직접 마운트
fsx_input = FileSystemInput(
file_system_id="fs-0123456789abcdef0",
file_system_type="FSxLustre",
directory_path="/fsx/imagenet/train",
file_system_access_mode="ro",
)
estimator.fit({"train": fsx_input})💡 개념: 같은 데이터셋으로 하이퍼파라미터 튜닝(HPO)을 수십~수백 번 반복하면 매번 S3에서 다운로드하는 비용이 누적된다. FSx for Lustre에 한 번 올려두면 모든 튜닝 잡이 고속으로 공유 접근해 전체 시간과 비용을 크게 줄인다. EFS는 처리량이 Lustre보다 낮지만 설정이 단순하고 영구 공유에 좋다. 핵심 판단 기준: 반복·고처리량 = Lustre, 공유·범용 = EFS, 1회성 대용량 스트리밍 = S3 Pipe.
원시 CSV·JSON·이미지를 그대로 학습에 쓰면 파싱 오버헤드와 작은 파일 문제로 I/O가 느려진다. ML은 두 가지 포맷을 선호한다.
| 포맷 | 구조 | 강점 | 언제 쓰나 |
|---|---|---|---|
| CSV | 행 기반 텍스트 | 사람이 읽음, 어디서나 지원 | 소규모, 빠른 확인 |
| JSON / JSON Lines | 행 기반 반정형 | 스키마 유연 | 로그 원본, 레이블링 매니페스트 |
| Parquet | 컬럼형 바이너리 | 컬럼 선택 읽기, 높은 압축 | 정형 피처 분석·ETL, Athena·Glue·Spark |
| RecordIO-protobuf | 레코드 묶음 바이너리 | 순차 읽기·Pipe 스트리밍 최적 | SageMaker 내장 알고리즘 대용량 학습 |
| TFRecord / tar 샤드 | 레코드 묶음 | 작은 파일 통합 | 이미지·오디오 수백만 개 |
RecordIO-protobuf는 SageMaker 내장 알고리즘의 권장 포맷이다. 여러 레코드를 하나의 큰 바이너리로 묶어 순차 읽기와 Pipe 모드 스트리밍에 최적이다.
import io, numpy as np
import sagemaker.amazon.common as smac
# numpy 행렬을 RecordIO-protobuf로 직렬화해 S3 업로드
buf = io.BytesIO()
smac.write_numpy_to_dense_tensor(buf, X_train.astype("float32"), y_train.astype("float32"))
buf.seek(0)
import boto3
boto3.client("s3").upload_fileobj(buf, "my-lake", "features/train/data.recordio")Parquet는 컬럼형(columnar) 저장 포맷이다. 행 단위가 아니라 컬럼 단위로 저장해서 ① 필요한 컬럼만 읽고(projection pushdown), ② 컬럼별 압축률이 높고, ③ Athena·Glue·Spark가 네이티브로 읽는다. 정형 피처 데이터의 사실상 표준이다.
import pandas as pd
# CSV 대비 Parquet은 컬럼 선택 읽기 + 높은 압축 → ETL·분석 I/O 절감
df.to_parquet("s3://my-lake/features/train.parquet", engine="pyarrow", compression="snappy")
# 학습 시 일부 컬럼만 필요하면 그 컬럼만 스캔 → I/O 대폭 감소
cols = pd.read_parquet("s3://my-lake/features/train.parquet", columns=["age", "amount", "label"])[행 기반 CSV] 행1: a,b,c,d,e | 행2: a,b,c,d,e | ... → 3개 컬럼만 필요해도 전부 스캔
[컬럼형 Parquet] a열 전체 | b열 전체 | c열 전체 | ... → 필요한 열 블록만 읽음
💡 개념: 행 기반 포맷(CSV)은 한 행을 통째로 읽어야 해서 50개 컬럼 중 3개만 필요해도 전부 스캔한다. 컬럼형 포맷(Parquet)은 컬럼별로 따로 저장돼 필요한 3개만 읽는다. 게다가 같은 컬럼의 값은 타입·분포가 비슷해 압축이 잘 된다. 그래서 정형 데이터 분석·ETL은 Parquet, SageMaker 내장 알고리즘의 대용량 순차 학습은 RecordIO-protobuf가 정답으로 자주 나온다.
수백만 개의 작은 이미지·JSON을 S3에 그대로 두면 객체당 요청 오버헤드로 학습이 느려진다.
ShardedByS3Key가 제대로 동작한다. 샤딩은 S3 객체 단위라, 단일 거대 파일 하나는 인스턴스별로 쪼개지지 않는다.⚠️ 함정: "데이터가 크니까 ShardedByS3Key를 켰다"고 끝이 아니다. 데이터가 여러 개의 S3 객체로 나뉘어 있어야 분배 효과가 난다. 단일 100GB 파일 하나에 샤딩을 걸면 아무 일도 일어나지 않는다.
데이터레이크는 "그냥 S3에 던지는 곳"이 아니다. 어떻게 배치하느냐가 이후 모든 스캔 비용을 좌우한다.
s3://bucket/dt=2026-06-26/region=kr/ 처럼 자주 필터링하는 키로 디렉터리를 나눈다. Athena·Spark가 필요 없는 파티션을 통째로 건너뛴다(partition pruning).⚠️ 함정: 학습 데이터를 Glacier 계열에 두면 저장 비용은 싸지만 복원(restore) 지연 때문에 학습 잡이 바로 읽지 못한다. "즉시 학습에 사용" 요건이 있으면 아카이브 스토리지는 오답이다.
데이터를 여러 번 반복해서 읽는가?
├─ 예 → 여러 노드가 동시에 고처리량으로 읽는가?
│ ├─ 예 → FSx for Lustre (S3 연동 캐시)
│ └─ 아니오 → EFS (공유·범용, 설정 단순)
└─ 아니오 → 데이터가 큰가?
├─ 예 → 순차 접근이면 S3 + Pipe
│ 랜덤 접근 필요하면 S3 + FastFile
└─ 아니오 → S3 + File (가장 단순)
내일은 이 데이터가 애초에 어디서 흘러들어오는가(Kinesis·Glue, 배치 vs 스트리밍)를 다룬다.
선택지를 클릭하면 정답·해설이 펼쳐집니다.
문제 1
800GB 학습 데이터를 ml.p3 인스턴스 4대로 분산 학습하려 한다. GPU가 데이터 복사를 기다리며 노는 시간을 최소화하면서 각 인스턴스가 데이터의 다른 조각만 읽게 하려면?
문제 2
같은 ImageNet 데이터셋으로 하이퍼파라미터 튜닝을 200회 반복하는데, 매번 S3에서 다운로드하는 시간이 누적되어 비용이 크다. 가장 적절한 스토리지 전략은?
문제 3
50개 컬럼의 정형 피처 테이블에서 분석·ETL 시 매번 3~5개 컬럼만 읽는다. I/O와 저장 비용을 동시에 줄이는 포맷은?
문제 4
SageMaker 내장 알고리즘으로 대용량 데이터를 Pipe 모드 순차 스트리밍 학습할 때 권장되는 직렬화 포맷은?
문제 5
여러 데이터 사이언티스트의 노트북과 여러 처리 잡이 동일한 중간 규모 데이터셋을 POSIX 파일 시스템처럼 동시에 공유·수정해야 한다. 설정이 단순하고 탄력적으로 확장되는 선택은?