CPU ‐ GPU 연동 부하테스트 - 100-hours-a-week/5-yeosa-wiki GitHub Wiki

1. 개요

  • 연동 후 부하테스트를 진행하여 기존에 cpu 서버에서 임베딩을 진행하던 것 대비 얼마나 속도가 향상되었는지 확인하고자 함.

2. 부하 테스트 개요 및 트래픽 추산 (클라우드팀 전달용)

a. 부하 테스트 수행 및 네트워크 트래픽 요약 보고서 (GCS 동일 Region 기준)

가. 테스트 개요

  • 총 테스트 횟수: 3회
    • S3 대상: 2회
    • GCS 대상: 1회 (VM과 동일 리전)
  • 테스트 도구: k6
  • 부하 조건:
    • 가상 유저 수: 30명
    • 테스트 지속 시간: 10분
    • 유저당 요청 간 간격: 3~5초
    • 요청당 포함 이미지 수: 30~50장 (평균 40장)
  • 총 유저 요청 수: 약 1,800건

나. VM 구성 및 네트워크 구조

구성 요소 역할 비고
CPU 서버 #1 k6 부하 생성 Public IP 통해 내부 CPU 서버에 요청
CPU 서버 #2 FastAPI 서버 (입력 수신 및 처리) GCS에서 이미지 로드, GPU 서버에 전달
GPU 서버 이미지 임베딩 처리 임베딩 결과를 CPU 서버로 반환
스토리지 S3 (2회), GCS (1회) GCS는 VM과 동일 리전에 위치함
  • VM 간 구성:
    • GCP 동일 리전, 단 서로 다른 zone
    • VM 간 통신: Public IP 사용
    • GCS 접근: 동일 리전이므로 아웃바운드 요금 없음
    • S3 접근: 외부 트래픽 발생 (인터넷 아웃바운드)

다. 트래픽 구조 및 추정

  • 이미지 1장 평균 크기: 150KB 기준
  • 요청 1건당 트래픽
    • 입력 전송 (CPU → GPU):
      • 평균 40장 × 150KB = 6.00MB
    • 임베딩 결과 반환 (GPU → CPU):
      • 평균 40장 × 2KB = 0.08MB
    • 합계: 6.08MB / 요청
  • 전체 테스트 트래픽
    • 요청 수: 1,800건
    • 총 트래픽:
      • 1,800 × 6.08MB = 10,944MB ≒ 10.69GB

3. 테스트할 시나리오

  • 시나리오 1 : cpu 서버에서 이미지 로딩 & 임베딩 모두 진행
  • 시나리오 2 : cpu 서버에서 이미지 로딩 & 디코딩 후, gpu 서버에서 임베딩 진행
  • 시나리오 3 : cpu 서버에서 요청 전달 후, gpu 서버에서 이미지 로딩 & 임베딩 진행

4. 테스트 결과

  • 초기 Serialized Queue로 구현한 코드

asdf_image

- 코드를 확인한 결과 기존에 serialize queue를 넣었던 것을 확인하여 그 부분을 개선하고 재테스트하고자 함.

a. 가설: cpu 서버에서 로딩 및 디코딩한 것보다 gpu 서버에서 로딩 및 디코딩하는 구조가 더 빠를 것이다. - 참

가. GPU 이미지 로딩 + 디코딩 + 임베딩

asdf_image 1

  • 리소스 사용량
cpu mem gpu gpu mem
cpu 서버 2.96% 9.13% - -
gpu 서버 81.81% 26.12% 27.77% 9.91%
  • 소요 시간 : 6.7s(p95)

나. CPU 이미지 로딩 + 디코딩 + 임베딩

asdf_image 2

  • 소요 시간 : 54s(p95)

가설1 결과: 참

cpu에서 임베딩을 돌린 결과, 동일 k6 test에서 처리 시간이 매우 높고 요청 간 시간 차이가 큼

b. 요청 처리 과정의 병목 가능 지점 식별

가. print해야 할 부분:

  • 이미지 로딩 및 디코딩 시간
  • 직렬화 시간(디폴트: gpu에서 요청 직렬화, cpu 디코딩이라면 cpu에서 직렬화하는 시간도)
  • 전송 시간 (cpu에서 보낸 시간과 gpu에서 받은 시간, gpu에서 응답 보낸 시간과 cpu에서 받은 시간)
  • 역직렬화 시간(디폴트: cpu에서 응답 역직렬화, cpu 디코딩이라면 gpu에서 역렬화하는 시간도)

나. 테스트 순서:

  • 깃헙 브랜치
    • cpu에서 로딩 및 디코딩: #91(cpu), #5(gpu)
    • gpu에서 로딩 및 디코딩: #85(cpu), #7(gpu)

다. 로컬 환경

테스트는 로컬에서 진행함. 테스트하고자 하는 항목이 임베딩이 얼마나 빨라졌는지가 아닌 ‘cpu 로딩 및 디코딩 시, 직렬화 및 전송 시간 체크’가 목적이므로 로컬 환경에서 충분하다 판단함

  • cpu에서 로딩 및 디코딩: #91(cpu), #5(gpu)

  • 로컬

    | 테스트 | cpu | gpu | 클라이언트 기준 시간 |
    | --- | --- | --- | --- |
    | 1 | [INFO] 이미지 로딩 및 디코딩 완료: 1.10 s
    [INFO] 직렬화 완료: 78.98 ms
    [INFO] GPU 서버 응답 수신: 1.06 s
    [INFO] 응답 역직렬화 완료: 2.89 ms | [INFO] 역직렬화 완료: 67.70 ms
    [INFO] 임베딩 완료 - 처리 이미지 수: 30, 소요 시간: 502.09 ms
    [INFO] 응답 직렬화 완료: 1.65 ms
    [INFO] 응답 전송 직전 - 총 처리 시간: 1.04 s | 2.27 s |
    | 2 | [INFO] 이미지 로딩 및 디코딩 완료: 895.25 ms
    [INFO] 직렬화 완료: 104.14 ms
    [INFO] GPU 서버 응답 수신: 1.24 s
    [INFO] 응답 역직렬화 완료: 12.93 ms | [INFO] 역직렬화 완료: 69.92 ms
    [INFO] 임베딩 완료 - 처리 이미지 수: 30, 소요 시간: 612.62 ms
    [INFO] 응답 직렬화 완료: 3.25 ms
    [INFO] 응답 전송 직전 - 총 처리 시간: 1.19 s | 2.28 s |
    | 3 | [INFO] 이미지 로딩 및 디코딩 완료: 813.21 ms
    [INFO] 직렬화 완료: 80.43 ms
    [INFO] GPU 서버 응답 수신: 1.03 s
    [INFO] 응답 역직렬화 완료: 2.87 ms | [INFO] 역직렬화 완료: 57.06 ms
    [INFO] 임베딩 완료 - 처리 이미지 수: 30, 소요 시간: 443.38 ms
    [INFO] 응답 직렬화 완료: 2.12 ms
    [INFO] 응답 전송 직전 - 총 처리 시간: 1.01 s | 1.94 s |
    | 4 | [INFO] 이미지 로딩 및 디코딩 완료: 1.05 s
    [INFO] 직렬화 완료: 92.90 ms
    [INFO] GPU 서버 응답 수신: 1.20 s
    [INFO] 응답 역직렬화 완료: 2.02 ms | [INFO] 역직렬화 완료: 79.52 ms
    [INFO] 임베딩 완료 - 처리 이미지 수: 30, 소요 시간: 514.04 ms
    [INFO] 응답 직렬화 완료: 1.67 ms
    [INFO] 응답 전송 직전 - 총 처리 시간: 1.17 s | 2.37 s |
    | 5 | [INFO] 이미지 로딩 및 디코딩 완료: 725.54 ms
    [INFO] 직렬화 완료: 99.19 ms
    [INFO] GPU 서버 응답 수신: 886.17 ms
    [INFO] 응답 역직렬화 완료: 2.85 ms | [INFO] 역직렬화 완료: 60.90 ms
    [INFO] 임베딩 완료 - 처리 이미지 수: 30, 소요 시간: 416.94 ms
    [INFO] 응답 직렬화 완료: 1.76 ms
    [INFO] 응답 전송 직전 - 총 처리 시간: 868.00 ms | 1.73 s |
    
- gpu에서 로딩 및 디코딩: #85(cpu), #7(gpu)
- 로컬 테스트
    
    ```
    | 테스트 | cpu | gpu | 클라이언트 기준 시간 |
    | --- | --- | --- | --- |
    | 1 | [START] 이미지 임베딩 요청 시작 - 총 이미지 수: 30
    [INFO] GPU 서버 전송 시작 시각: 2025-05-21 13:29:26.090
    [INFO] GPU 서버 응답 수신 시각: 2025-05-21 13:29:27.571
    [INFO] 요청-응답 소요 시간: 1.48 s
    [INFO] 응답 역직렬화 완료: 4.88 ms | [START] GPU 서버: 임베딩 요청 수신
    [INFO] 요청 수신 시각: 2025-05-21 13:29:26.103
    [INFO] 이미지 로딩 및 디코딩 완료: 1.05 s
    [INFO] 임베딩 완료: 407.08 ms
    [INFO] 응답 직렬화 완료: 1.57 ms
    [INFO] 응답 전송 시각: 2025-05-21 13:29:27.564
    [INFO] 총 처리 시간: 1.46 s | 1.50 s |
    | 2 | [START] 이미지 임베딩 요청 시작 - 총 이미지 수: 30
    [INFO] GPU 서버 전송 시작 시각: 2025-05-21 13:30:00.995
    [INFO] GPU 서버 응답 수신 시각: 2025-05-21 13:30:02.459
    [INFO] 요청-응답 소요 시간: 1.46 s
    [INFO] 응답 역직렬화 완료: 4.25 ms | [START] GPU 서버: 임베딩 요청 수신
    [INFO] 요청 수신 시각: 2025-05-21 13:30:01.006
    [INFO] 이미지 로딩 및 디코딩 완료: 1.01 s
    [INFO] 임베딩 완료: 433.87 ms
    [INFO] 응답 직렬화 완료: 1.30 ms
    [INFO] 응답 전송 시각: 2025-05-21 13:30:02.450
    [INFO] 총 처리 시간: 1.44 s | 1.49 s |
    | 3 | [INFO] GPU 서버 전송 시작 시각: 2025-05-21 13:30:28.692
    [INFO] GPU 서버 응답 수신 시각: 2025-05-21 13:30:29.885
    [INFO] 요청-응답 소요 시간: 1.19 s
    [INFO] 응답 역직렬화 완료: 2.23 ms | [INFO] 요청 수신 시각: 2025-05-21 13:30:28.696
    [INFO] 이미지 로딩 및 디코딩 완료: 823.95 ms
    [INFO] 임베딩 완료: 354.80 ms
    [INFO] 응답 직렬화 완료: 1.55 ms
    [INFO] 응답 전송 시각: 2025-05-21 13:30:29.877
    [INFO] 총 처리 시간: 1.18 s | 1.20 s |
    | 4 | [INFO] GPU 서버 전송 시작 시각: 2025-05-21 13:30:59.166
    [INFO] GPU 서버 응답 수신 시각: 2025-05-21 13:31:00.467
    [INFO] 요청-응답 소요 시간: 1.30 s
    [INFO] 응답 역직렬화 완료: 2.88 ms | [INFO] 요청 수신 시각: 2025-05-21 13:30:59.169
    [INFO] 이미지 로딩 및 디코딩 완료: 912.77 ms
    [INFO] 임베딩 완료: 375.77 ms
    [INFO] 응답 직렬화 완료: 1.47 ms
    [INFO] 응답 전송 시각: 2025-05-21 13:31:00.459
    [INFO] 총 처리 시간: 1.29 s | 1.31 s |
    | 5 | [INFO] GPU 서버 전송 시작 시각: 2025-05-21 13:32:26.911
    [INFO] GPU 서버 응답 수신 시각: 2025-05-21 13:32:28.613
    [INFO] 요청-응답 소요 시간: 1.70 s
    [INFO] 응답 역직렬화 완료: 3.31 ms | [INFO] 요청 수신 시각: 2025-05-21 13:32:26.921
    [INFO] 이미지 로딩 및 디코딩 완료: 1.30 s
    [INFO] 임베딩 완료: 377.49 ms
    [INFO] 응답 직렬화 완료: 1.62 ms
    [INFO] 응답 전송 시각: 2025-05-21 13:32:28.605
    [INFO] 총 처리 시간: 1.68 s | 1.72 s |
| 항목 | 평균 |
| --- | --- |
| **요청 직렬화** | **91.13 ms** |
| **요청 역직렬화** | **67.02 ms** |
| **응답 역직렬화** | **4.71 ms** |
| **응답 직렬화** | **2.09 ms** |
| **클라이언트 기준 총 응답 시간 (CPU 디코딩)** | **2.12 s** |
| **클라이언트 기준 총 응답 시간 (GPU 디코딩)** | **1.44 s** |
  • cpu 디코딩 진행하면 gpu 대비 0.68s 지연 시간 증가함
    • 요청 직렬화 및 역직렬화 테스크 추가됨
  • 응답 직렬화 및 역직렬화
    • 2 방식(디코딩 위치 차이) 모두 발생
    • 임베딩의 직렬화 및 역직렬화에 소요되는 시간은 비교적 작음
  • 요청을 직렬화&역직렬화
    • 이미지에 대한 np.ndarray를 처리하는데 시간이 많이 소요
    • 직렬화&역직렬화 자체로는 대략 158.15ms가 추가된다.
  • 전체 요청 시간은 0.68s가 추가된다.
  • 로컬 환경에서는 서버 간 전송에 cpu 디코딩 시 0.020.05s, gpu 디코딩 시 0.010.02s가 소요
    • 로컬 프로세스 간 전송 시간 vm 환경보다 짧을 것
    • 실제 vm 환경에서의 전송 시간을 확인 → 정밀 측정

라. vm 환경 테스트

VM에 실제로 cpu, gpu 띄워서 직렬화, 역직렬화, 임베딩, 전송 시간을 측정한다.

주의사항: s3 말고 gcs를 이용해서 테스트 진행 (비용 이슈)

  • gcs 비용은 크레딧으로 충당 가능하고 s3는 지원금 100만원에서 까임

  • gcs 버킷으로의 트래픽은 동일 리전 내에 있기에 트래픽 비용이 발생하지 않음

  • cpu에서 로딩 및 디코딩: #91(cpu), #5(gpu)

  • vm 테스트

    | 테스트 | cpu | gpu | 클라이언트 기준 시간 |
    | --- | --- | --- | --- |
    | 1 | [INFO] 이미지 로딩 및 디코딩 완료: 391.52 ms
    [INFO] 직렬화 완료: 144.78 ms
    [INFO] GPU 서버 응답 수신: 1.12 s
    [INFO] 응답 역직렬화 완료: 4.31 ms | [INFO] 역직렬화 완료: 39.06 ms
    [INFO] 임베딩 완료 - 처리 이미지 수: 30, 소요 시간: 402.88 ms
    [INFO] 응답 직렬화 완료: 4.16 ms
    [INFO] 응답 전송 직전 - 총 처리 시간: 1.09 s | 1.83 s |
    | 2 | [INFO] 이미지 로딩 및 디코딩 완료: 210.16 ms
    [INFO] 직렬화 완료: 145.05 ms
    [INFO] GPU 서버 응답 수신: 988.93 ms
    [INFO] 응답 역직렬화 완료: 3.98 ms | [INFO] 역직렬화 완료: 39.12 ms
    [INFO] 임베딩 완료 - 처리 이미지 수: 30, 소요 시간: 195.91 ms
    [INFO] 응답 직렬화 완료: 3.72 ms
    [INFO] 응답 전송 직전 - 총 처리 시간: 965.09 ms | 1.44 s |
    | 3 | [INFO] 이미지 로딩 및 디코딩 완료: 206.74 ms
    [INFO] 직렬화 완료: 138.72 ms
    [INFO] GPU 서버 응답 수신: 962.38 ms
    [INFO] 응답 역직렬화 완료: 3.91 ms | [INFO] 역직렬화 완료: 39.28 ms
    [INFO] 임베딩 완료 - 처리 이미지 수: 30, 소요 시간: 182.61 ms
    [INFO] 응답 직렬화 완료: 4.09 ms
    [INFO] 응답 전송 직전 - 총 처리 시간: 939.54 ms | 1.34 s |
    | 4 | [INFO] 이미지 로딩 및 디코딩 완료: 312.04 ms
    [INFO] 직렬화 완료: 194.47 ms
    [INFO] GPU 서버 응답 수신: 1.01 s
    [INFO] 응답 역직렬화 완료: 5.17 ms | [INFO] 역직렬화 완료: 39.11 ms
    [INFO] 임베딩 완료 - 처리 이미지 수: 30, 소요 시간: 183.27 ms
    [INFO] 응답 직렬화 완료: 3.85 ms
    [INFO] 응답 전송 직전 - 총 처리 시간: 982.53 ms | 1.55 s |
    | 5 | [INFO] 이미지 로딩 및 디코딩 완료: 209.69 ms
    [INFO] 직렬화 완료: 143.42 ms
    [INFO] GPU 서버 응답 수신: 893.00 ms
    [INFO] 응답 역직렬화 완료: 4.18 ms | [INFO] 역직렬화 완료: 39.04 ms
    [INFO] 임베딩 완료 - 처리 이미지 수: 30, 소요 시간: 175.30 ms
    [INFO] 응답 직렬화 완료: 4.54 ms
    [INFO] 응답 전송 직전 - 총 처리 시간: 868.27 ms | 1.27 s |
    
- gpu에서 로딩 및 디코딩: #85(cpu), #7(gpu)
- vm 테스트
    
    ```
    | 테스트 | cpu | gpu | 클라이언트 기준 시간 |
    | --- | --- | --- | --- |
    | 1 | [INFO] GPU 서버 전송 시작 시각: 2025-05-21 05:19:19.023
    [INFO] GPU 서버 응답 수신 시각: 2025-05-21 05:19:20.243
    [INFO] 요청-응답 소요 시간: 1.22 s
    [INFO] 응답 역직렬화 완료: 4.09 ms | [INFO] 요청 수신 시각: 2025-05-21 05:19:19.052
    [INFO] 이미지 로딩 및 디코딩 완료: 444.71 ms
    [INFO] 임베딩 완료: 748.98 ms
    [INFO] 응답 직렬화 완료: 4.05 ms
    [INFO] 응답 전송 시각: 2025-05-21 05:19:20.251
    [INFO] 총 처리 시간: 1.20 s | 1.33 s |
    | 2 | [INFO] GPU 서버 전송 시작 시각: 2025-05-21 05:23:13.842
    [INFO] GPU 서버 응답 수신 시각: 2025-05-21 05:23:14.287
    [INFO] 요청-응답 소요 시간: 445.26 ms
    [INFO] 응답 역직렬화 완료: 4.26 ms | [INFO] 요청 수신 시각: 2025-05-21 05:23:13.864
    [INFO] 이미지 로딩 및 디코딩 완료: 238.35 ms
    [INFO] 임베딩 완료: 191.11 ms
    [INFO] 응답 직렬화 완료: 3.76 ms
    [INFO] 응답 전송 시각: 2025-05-21 05:23:14.298
    [INFO] 총 처리 시간: 434.02 ms | 472 ms |
    | 3 | [INFO] GPU 서버 전송 시작 시각: 2025-05-21 05:24:00.071
    [INFO] GPU 서버 응답 수신 시각: 2025-05-21 05:24:00.519
    [INFO] 요청-응답 소요 시간: 448.78 ms
    [INFO] 응답 역직렬화 완료: 4.07 ms | [INFO] 요청 수신 시각: 2025-05-21 05:24:00.093
    [INFO] 이미지 로딩 및 디코딩 완료: 233.84 ms
    [INFO] 임베딩 완료: 199.90 ms
    [INFO] 응답 직렬화 완료: 3.78 ms
    [INFO] 응답 전송 시각: 2025-05-21 05:24:00.531
    [INFO] 총 처리 시간: 438.15 ms | 495 ms |
    | 4 | [INFO] GPU 서버 전송 시작 시각: 2025-05-21 05:24:22.830
    [INFO] GPU 서버 응답 수신 시각: 2025-05-21 05:24:23.276
    [INFO] 요청-응답 소요 시간: 445.36 ms
    [INFO] 응답 역직렬화 완료: 3.83 ms | [INFO] 요청 수신 시각: 2025-05-21 05:24:22.853
    [INFO] 이미지 로딩 및 디코딩 완료: 237.43 ms
    [INFO] 임베딩 완료: 191.56 ms
    [INFO] 응답 직렬화 완료: 3.72 ms
    [INFO] 응답 전송 시각: 2025-05-21 05:24:23.287
    [INFO] 총 처리 시간: 433.35 ms | 802 ms |
    | 5 | [INFO] GPU 서버 전송 시작 시각: 2025-05-21 05:25:06.267
    [INFO] GPU 서버 응답 수신 시각: 2025-05-21 05:25:06.698
    [INFO] 요청-응답 소요 시간: 431.14 ms
    [INFO] 응답 역직렬화 완료: 4.15 ms | [INFO] 요청 수신 시각: 2025-05-21 05:25:06.290
    [INFO] 이미지 로딩 및 디코딩 완료: 231.87 ms
    [INFO] 임베딩 완료: 183.34 ms
    [INFO] 응답 직렬화 완료: 3.75 ms
    [INFO] 응답 전송 시각: 2025-05-21 05:25:06.710
    [INFO] 총 처리 시간: 419.66 ms | 542 ms |

결과 분석:

항목 값 목록 평균
1. 처리 시간 A 1.33 s, 472 ms, 495 ms, 802 ms, 542 ms 728.4 ms
2. 처리 시간 B 1.83 s, 1.44 s, 1.34 s, 1.55 s, 1.27 s 1.49 s
요청 직렬화 144.78, 145.05, 138.72, 194.47, 143.42 153.29 ms
요청 역직렬화 39.04, 39.11, 39.28, 39.12, 39.06 39.12 ms
응답 직렬화 4.16, 3.72, 4.09, 3.85, 4.54 4.07 ms
응답 역직렬화 4.18, 5.17, 3.91, 3.98, 4.31 4.31 ms
  • 이미지 로딩 및 디코딩은 어디서 하든 소요 시간 비슷(gpu를 활용하지 않는 연산)
  • 전체 평균 시간
    • gpu 로딩 시: 1.49 s
    • cpu 로딩 시: 728.4 ms
  • 요청 직렬화 및 역직렬화에 192.42ms 추가
  • 유저 입장에서는 761.6 ms

c. 추가 고려 사항: cpu 서버 로딩 및 디코딩 시, 트래픽 비용 증가

  • 트래픽 비용
    • 이미지를 cpu - gpu 전송 과정에서 트래픽 비용 발생
  • 현재 vm 세팅(cpu-gpu 다른 프로젝트에 있음)에서는 vpc가 달라서 내부 ip를 사용하지 못해 트래픽 비용이 발생
    • cpu에서 이미지를 gpu에 전송하는 것은 비용 문제가 될 수 있음

d. 분석 및 회고

  • 761.6ms는 부하테스트 상황에서는 오버헤드가 커질 수 있음
  • gpu에 cpu 사용률 체크 진행하여 gpu에서 cpu 리소스 여유 있는지 확인
    • 인물 분류 gpu 서버에서 cpu 사용량(로딩 및 디코딩은 cpu에서 진행)
    • cpu 30%, gpu 22.5% 사용
  • 임베딩 작업 역시 cpu, gpu 사용률이 크지 않았음
  • cpu 사용률 측면에서 gpu 서버에서 로딩 및 디코딩 가능

asdf_image 3

asdf_image 4

5. 결론: gpu 서버에서 임베딩 요청을 위한 이미지 로딩, 디코딩 진행

아래와 같은 근거들로 최종 결론 내림:

  • cpu - gpu 서버 간 이미지 전송 비용
    • vpc 다른 상황에서 퍼블릭 ip로 이미지 전송은 트래픽 비용 높음
  • 지연 시간
    • cpu 서버에서 로딩 및 디코딩 시, 이미지 피클링(cpu 서버)→언피클링(gpu 서버) 오버헤드 발생
      • 이미지는 사이즈가 커서 응답 피클링&언피클링에 비해 오버헤드 큼
  • gpu 서버 cpu 사용률 여유 있음
    • 로딩 및 디코딩에서 gpu 서버의 cpu 서버 사용 가능할만큼 리소스 여유 있음