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 / 요청
- 입력 전송 (CPU → GPU):
- 전체 테스트 트래픽
- 요청 수: 1,800건
- 총 트래픽:
- 1,800 × 6.08MB = 10,944MB ≒ 10.69GB
3. 테스트할 시나리오
- 시나리오 1 : cpu 서버에서 이미지 로딩 & 임베딩 모두 진행
- 시나리오 2 : cpu 서버에서 이미지 로딩 & 디코딩 후, gpu 서버에서 임베딩 진행
- 시나리오 3 : cpu 서버에서 요청 전달 후, gpu 서버에서 이미지 로딩 & 임베딩 진행
4. 테스트 결과
- 초기 Serialized Queue로 구현한 코드
- 코드를 확인한 결과 기존에 serialize queue를 넣었던 것을 확인하여 그 부분을 개선하고 재테스트하고자 함.
a. 가설: cpu 서버에서 로딩 및 디코딩한 것보다 gpu 서버에서 로딩 및 디코딩하는 구조가 더 빠를 것이다. - 참
가. GPU 이미지 로딩 + 디코딩 + 임베딩
- 리소스 사용량
cpu | mem | gpu | gpu mem | |
---|---|---|---|---|
cpu 서버 | 2.96% | 9.13% | - | - |
gpu 서버 | 81.81% | 26.12% | 27.77% | 9.91% |
- 소요 시간 : 6.7s(p95)
나. CPU 이미지 로딩 + 디코딩 + 임베딩
- 소요 시간 : 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.02
0.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 서버에서 로딩 및 디코딩 가능
5. 결론: gpu 서버에서 임베딩 요청을 위한 이미지 로딩, 디코딩 진행
아래와 같은 근거들로 최종 결론 내림:
- cpu - gpu 서버 간 이미지 전송 비용
- vpc 다른 상황에서 퍼블릭 ip로 이미지 전송은 트래픽 비용 높음
- 지연 시간
- cpu 서버에서 로딩 및 디코딩 시, 이미지 피클링(cpu 서버)→언피클링(gpu 서버) 오버헤드 발생
- 이미지는 사이즈가 커서 응답 피클링&언피클링에 비해 오버헤드 큼
- cpu 서버에서 로딩 및 디코딩 시, 이미지 피클링(cpu 서버)→언피클링(gpu 서버) 오버헤드 발생
- gpu 서버 cpu 사용률 여유 있음
- 로딩 및 디코딩에서 gpu 서버의 cpu 서버 사용 가능할만큼 리소스 여유 있음