num_workers는 프로세스 개수다PyTorch DataLoader의 num_workers는 스레드가 아니라 프로세스의 개수를 의미합니다.
num_workers=4라면, 독립적인 파이썬 프로세스 4개가 생성되어 병렬로 데이터 로딩 및 전처리를 수행합니다.
| 특징 | 프로세스 (Process) | 스레드 (Thread) |
|---|---|---|
| 정의 | 운영체제로부터 독립 자원을 할당받아 실행되는 프로그램 단위 | 프로세스 내부에서 실행되는 흐름 단위 |
| 메모리 | 독립 메모리 공간(코드, 데이터, 힙, 스택) 보유 | 코드·데이터·힙은 공유, 스택만 독립 |
| 생성/종료 | 느리고 비용 큼 | 빠르고 가벼움 |
| 자원 공유 | IPC (Inter-Process Communication)필요 | 프로세스 내 전역 변수, 파일 핸들 공유 |
| 안전성 | 다른 프로세스에 영향 없음 | 같은 프로세스의 다른 스레드에 영향 가능 |
💡 비유:
num_workers 설정 전략한 GPU에서 여러 네트워크를 동시에 학습할 경우, CPU 코어를 균등하게 나누는 것이 기본 전략입니다.
num_workers = 16 ÷ 4 = 4DataLoader 프로세스 수를 늘리면 각 프로세스 내부에서 NumPy, PyTorch 연산이 추가 스레드를 만들 수 있어 CPU 과부하가 발생합니다. 이를 방지하려면:
import os
import torch
# NumPy/OpenMP 스레드 제한
os.environ['OMP_NUM_THREADS'] = '1'
os.environ['MKL_NUM_THREADS'] = '1'
os.environ['OPENBLAS_NUM_THREADS'] = '1'
# PyTorch CPU 스레드 제한
torch.set_num_threads(1)
이렇게 하면 각 워커 프로세스 내부에서 연산 시 스레드 1개만 사용하게 되어, 프로세스 병렬화 이점만 살리고 스레드 오버헤드는 줄일 수 있습니다.
꼭 그렇진 않습니다.
DataLoader의 목적은 CPU에서 데이터를 병렬로 로딩·전처리하는 것이므로, NumPy를 효율적으로 쓰는 편이 더 나을 때가 많습니다.
import os
import torch
from torch.utils.data import DataLoader, Dataset
import numpy as np
# 스레드 제한
os.environ['OMP_NUM_THREADS'] = '1'
os.environ['MKL_NUM_THREADS'] = '1'
torch.set_num_threads(1)
class CustomDataset(Dataset):
def __len__(self):
return 1000
def __getitem__(self, idx):
arr = np.random.rand(3, 256, 256).astype(np.float32)
arr = np.abs(np.fft.fft2(arr))
return torch.from_numpy(arr), torch.randint(0, 10, (1,))
num_cores = os.cpu_count()
loader = DataLoader(CustomDataset(), batch_size=32, num_workers=num_cores, pin_memory=True)
for data, target in loader:
pass
num_workers = 프로세스 개수, 스레드가 아님os.environ과 torch.set_num_threads()로 제한 가능num_workers 설정