프로세스, 스레드, 그리고 CPU 최적화 전략 — PyTorch 'num_workers' 설명

Bean·2025년 8월 13일

프로그래밍

목록 보기
27/46

1. num_workers는 프로세스 개수다

PyTorch DataLoadernum_workers스레드가 아니라 프로세스의 개수를 의미합니다.
num_workers=4라면, 독립적인 파이썬 프로세스 4개가 생성되어 병렬로 데이터 로딩 및 전처리를 수행합니다.


2. 프로세스 vs 스레드 — 개념 확실히 잡기

특징프로세스 (Process)스레드 (Thread)
정의운영체제로부터 독립 자원을 할당받아 실행되는 프로그램 단위프로세스 내부에서 실행되는 흐름 단위
메모리독립 메모리 공간(코드, 데이터, 힙, 스택) 보유코드·데이터·힙은 공유, 스택만 독립
생성/종료느리고 비용 큼빠르고 가벼움
자원 공유IPC (Inter-Process Communication)필요프로세스 내 전역 변수, 파일 핸들 공유
안전성다른 프로세스에 영향 없음같은 프로세스의 다른 스레드에 영향 가능

💡 비유:

  • 프로세스 = 공장 (독립 건물과 설비를 가짐)
  • 스레드 = 공장 안 작업자 (같은 도구를 공유)

3. 여러 네트워크 학습 시 num_workers 설정 전략

한 GPU에서 여러 네트워크를 동시에 학습할 경우, CPU 코어를 균등하게 나누는 것이 기본 전략입니다.

예시

  • CPU 논리 코어: 16개
  • 동시에 학습할 네트워크: 4개
  • 각 네트워크의 num_workers = 16 ÷ 4 = 4

4. CPU 과부하 방지를 위한 스레드 제한

DataLoader 프로세스 수를 늘리면 각 프로세스 내부에서 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개만 사용하게 되어, 프로세스 병렬화 이점만 살리고 스레드 오버헤드는 줄일 수 있습니다.


5. NumPy 연산, 꼭 줄여야 할까?

꼭 그렇진 않습니다.
DataLoader의 목적은 CPU에서 데이터를 병렬로 로딩·전처리하는 것이므로, NumPy를 효율적으로 쓰는 편이 더 나을 때가 많습니다.

  • NumPy는 이미지 처리·배열 연산에서 직관적이고 빠른 API 제공
  • 성능 문제는 연산 자체가 아니라 과도한 멀티스레딩에서 발생
  • 따라서 스레드 제한 + 적절한 num_workers 설정이 핵심

6. 최적 예시 코드

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

7. 핵심 요약

  • num_workers = 프로세스 개수, 스레드가 아님
  • 프로세스 내부 스레드 수는 os.environtorch.set_num_threads()로 제한 가능
  • 여러 네트워크 학습 시 CPU 코어 수를 균등 분배해 num_workers 설정
  • NumPy 연산은 스레드 수만 관리하면 적극적으로 활용 가능

profile
AI developer

0개의 댓글