[멀티 프로세스] 단일 프로세스, 멀티 프로세스 성능 비교(리소스 사용량, 테스크별 지연시간) - 100-hours-a-week/5-yeosa-wiki GitHub Wiki

1. 개요

  • 멀티 프로세스에서 오히려 지연 시간이 늘어남. (gpu 서버에서 병목 발생)
  • 해당 원인을 아래와 같이 예측함.
    • 단일 프로세스에서는 cpu 바운드 테스크가 병목 지점
    • 멀티 프로세스에서는 i/o 바운드 테스크가 병목 지점 (cpu, gpu 리소스는 풀로 이용하고 있기 때문)
  • 할 일:
    • gpu 서버의 단일 프로세스, 멀티 프로세스에서 리소스 사용량, 지연 시간(이미지 로딩, 디코딩, 전처리) 측정
    • 멀티 프로세스에서 식별한 병목 지점 개선

2. 로깅 추가

a. 이미지 1장 로딩

    async def _download(self, file_name: str) -> bytes:
        """
        GCS에서 단일 이미지를 다운로드하고 RGB로 변환합니다.

        Args:
            file_name (str): GCS 내 파일 이름

        Returns:
            bytes: 로드된 이미지 바이트

        """
        start = time.time()
        image_bytes = await self.client.download(
            bucket=self.bucket_name, object_name=file_name
        )
        end = time.time()
        print(f"[INFO] 이미지 로딩 완료 : {format_elapsed(end - start)}")
        # 
        return image_bytes

b. 이미지 디코딩

# 공통 디코더
def decode_image_cv2(image_bytes: bytes, label: str) -> np.ndarray:

    start = time.time()
    nparr = np.frombuffer(image_bytes, np.uint8)
    img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    end = time.time()
    
    print(f"[INFO] 디코딩 완료 : {format_elapsed(end - start)}")
    return img

c. 이미지 전처리 & 임베딩

import torch
import time
from concurrent.futures import ThreadPoolExecutor

def format_elapsed(t: float) -> str:
    return f"{t * 1000:.2f} ms" if t < 1 else f"{t:.2f} s"

def embed_images(
    model, preprocess, images, filenames, batch_size=32, device="cuda"
):
    # 이미지 전처리를 배치 단위로 수행
    preprocessed_batches = []
    t1 = time.time()
        
    for i in range(0, len(images), batch_size):
        batch_images = images[i:i + batch_size]
        preprocessed_batch = preprocess(batch_images)
        preprocessed_batches.append(preprocessed_batch)
    t2 = time.time()
    print(f"[INFO] 전처리 완료: {format_elapsed(t2 - t1)}")
    # 결과를 저장할 딕셔너리
    results = {}
    
    t3 = time.time()
    # 배치 단위로 임베딩 수행
    for i, batch in enumerate(preprocessed_batches):
        batch_filenames = filenames[i * batch_size:(i + 1) * batch_size]
        
        # GPU로 데이터 이동
        image_input = batch.to(device)
        
        # 임베딩 생성
        with torch.no_grad():
            batch_features = model.encode_image(image_input)
        
        # CPU로 결과 이동 및 저장
        batch_features = batch_features.cpu()
        for filename, feature in zip(batch_filenames, batch_features):
            results[filename] = feature.cpu()

    t4 = time.time()
    print(f"[INFO] 임베딩 완료: {format_elapsed(t4 - t3)}")

    return results

3. 테스트 결과

  • 추후 리소스 재확인용 테스트 시간 기록
    • 6.11 3시 45분~55분: multiprocess
    • 6.11 5시 11분~5시 21분: singleprocess

단일1

single process gpu cpu gpu mem cpu mem
% 86.96 80.06 33.23 53.07
multi process gpu cpu gpu mem cpu mem
% 98.9 91.73 32.85 66.59
  • multi process에서 spawn() 시스템 콜로 모델 로딩함에 따라 cpu 메모리 이용량 증가
  • gpu 메모리는 늘지 않은 이유:
    • torch는 “사용 시점에만” gpu 메모리 점유

b. k6 report

가. multi process

단일2

나. single process

단일3

c. 테스크별 처리 시간

|  | single process | multi process | 비교 (single→multi) |
| --- | --- | --- | --- |
| 디코딩 | 단일: 15.78 ms
최소값: 7.27 ms
평균값: 24.80 ms
최대값: 278.22 ms
 | 단일: 16.18 ms
최소값: 6.86 ms
평균값: 30.47 ms
최대값: 380.92 ms | 평균 +22.9% |
| 로딩 | 단일: 232.66 ms
최소값: 10.08 ms
평균값: 204.48 ms
최대값: 541.40 ms | 최소값: 1.09 ms
평균값: 105.82 ms
최대값: 996.07 ms | 평균 -48.2% |
| 로딩 및 디코딩 | 단일: 232.66 ms
최소값: 76.89 ms
평균값: 300.36 ms
최대값: 647.85 ms | 단일: 238.69 ms
최소값: 1.01 ms
평균값: 320.69 ms
최대값: 985.95 ms | 평균 +6.8% |
| 전처리 | 단일: 63.96 ms
최소값: 36.01 ms
평균값: 105.93 ms
최대값: 641.05 ms | 단일: 66.06 ms
최소값: 1.04 ms
평균값: 262.54 ms
최대값: 991.44 ms | 평균 +147.7% |
| 임베딩 | 단일: 183.38 ms
최소값: 66.22 ms
평균값: 218.94 ms
최대값: 562.11 ms | 단일: 183.63 ms
최소값: 1.00 ms
평균값: 466.93 ms
최대값: 999.76 ms | 평균 +113.3% |
  • 멀티 프로세스 전환 후, 평균 처리 시간은 대체로 증가
  • 특히 전처리, 임베딩에서 2배 이상 증가
  • i/o 바운드 테스크인 로딩은 2배 감소
  • cpu, gpu 리소스를 풀로 이용함에 따라 리소스 경합이 심화되어 오버헤드 증가

4. 결론: gpu 서버 워커 프로세스 2개로 감축 예정

  • cpu, gpu 리소스가 워커 프로세스 3개를 감당하기에 충분치 않음
  • 워커 프로세스를 3 → 2개로 줄여서 i/o 속도 개선을 누리면서 리소스 경합을 완화하여 연산 중심 테스크에서도 속도 개선 달성하고자 함