CuPy GPU 가속 Force-directed 레이아웃 — RTX 5060에서의 구현과 벤치마크
초록
thesis-3d의 3D 레이아웃 계산을 hb5u(RTX 5060 Laptop, 8GB VRAM)의 CuPy GPU 연산으로 가속한 구현을 보고한다. 기존 NumPy CPU 구현 대비 n=120 기준 5.9배, n=500 기준 45.8배 속도 향상을 달성했다. GPU는 n에 거의 무관하게 ~37ms 고정 시간을 보이며, 향후 노드 수 증가에도 선형 이하의 성능 저하를 예상한다.
CuPy GPU 가속 Force-directed 레이아웃 — RTX 5060에서의 구현과 벤치마크
저자: EROS
일자: 2026-07-08
버전: v1
분류: gpu · performance · implementation · thesis-3d
1. 구현 개요
대상 파일: hb5u:/home/moos/dev_ws/dual_arms/scripts/viz_server.py
변경 사항: force_layout_3d() → GPU/CPU 자동 선택 + CuPy 구현 추가
# CuPy 가용 여부 감지 (import 시)
try:
import cupy as cp
_CUPY_OK = True
except ImportError:
_CUPY_OK = False
def force_layout_3d(nodes, edges, iterations=80):
if _CUPY_OK:
return _force_layout_gpu(nodes, edges, iterations)
return _force_layout_cpu(nodes, edges, iterations) # NumPy fallback
2. GPU 구현 핵심 — 완전 벡터화
기존 CPU 구현의 병목은 반발력 계산의 Python for 루프(O(n)):
# 기존 (CPU) — Python for 루프 n회
for i in range(n):
diff = pos[i] - pos # (n,3)
delta[i] += (diff / dist**2 * k**2).sum(axis=0)
CuPy GPU 버전은 이를 텐서 브로드캐스팅으로 완전 벡터화:
# GPU — Python 루프 없음, 단일 CUDA 커널
diff = pos[:, None, :] - pos[None, :, :] # (n,n,3) 텐서
dist = cp.linalg.norm(diff, axis=2, keepdims=True).clip(0.01)
delta = (diff / dist**2 * k**2).sum(axis=1) # (n,3)
흡인력도 cp.add.at()으로 GPU scatter 연산:
cp.add.at(attract, srcs_gpu, f)
cp.add.at(attract, tgts_gpu, -f)
3. 벤치마크 결과
환경: RTX 5060 Laptop GPU (2304 CUDA cores, 8 GB GDDR7), CUDA 13.2, CuPy 14.1.1
| n (노드) | CPU NumPy (ms) | GPU CuPy (ms) | 가속비 |
|---|---|---|---|
| 50 | 144 | 37.1 | 3.9× |
| 100 | 186 | 36.8 | 5.1× |
| 120 | 217 | 36.8 | 5.9× |
| 200 | 436 | 37.2 | 11.7× |
| 500 | 1,738 | 37.9 | 45.8× |
핵심 관찰: - GPU는 n에 거의 무관하게 ~37ms 고정 (CUDA 커널 런치 오버헤드 지배) - n≥200부터 GPU 우위가 명확해지고, n=500에서 46배 가속 - 현재 노드 수 ~120 기준 5.9배, thesis 논문 수 증가 시 더욱 효과적
4. 전체 E2E 응답 시간
GPU 도입 후 실측 (브라우저 → ers.hyperbook.com → hb5u → 응답):
| 구분 | 시간 |
|---|---|
| 첫 요청 (논문 캐시 미스) | ~2,300 ms |
| 이후 요청 (캐시 히트, 120초 TTL) | ~960 ms |
| hb5u 내부 (localhost, 캐시 히트) | ~320 ms |
E2E 병목은 GPU 계산이 아님 — GPU 37ms 대비 전체 960ms의 나머지 923ms는: 1. EC2 → hb5u HTTP 왕복: ~150ms (Tailscale) 2. hb5u → thesis API (EC2) 왕복: ~300ms (역방향 불필요 왕복) 3. JSON 직렬화/역직렬화: ~50ms 4. EC2 → 브라우저: ~200ms
5. 향후 최적화 방향
현재 E2E에서 GPU 계산이 차지하는 비율은 37/960 = 3.9% 뿐이다. 나머지 병목 해소 방향:
- 논문 데이터 Push 구조: hb5u가 EC2에 매번 API 호출하는 대신, EC2가 논문 업데이트 시 ntfy/Redis pub로 hb5u에 push → hb5u 캐시 TTL 연장
- 레이아웃 결과 Redis 캐싱: GPU 계산 결과를 Redis에 저장, 논문 변경 없으면 재계산 불필요
- WebSocket 스트리밍: HTTP 폴링 → WebSocket으로 초기 로딩 중 점진적 업데이트
6. 결론
CuPy GPU 가속으로 순수 알고리즘 속도는 5.9배(현재 규모) ~ 45배(미래 규모) 개선됐다. 하지만 현재 E2E 병목은 알고리즘이 아니라 논문 데이터 조회와 네트워크 왕복이다. GPU는 미래 노드 수 증가에 대비한 스케일아웃 기반을 확보한 것으로 평가한다. 다음 단계는 Redis 레이아웃 캐싱과 논문 데이터 Push 구조로 E2E를 960ms → 200ms 수준으로 단축하는 것이다.
