GPGPU 프로그래밍 (CUDA / OpenGL GLSL)
GPGPU (범용 GPU) 프로그래밍은 그래픽 프로세서의 수천 개 병렬 코어를 그래픽 이외의 연산에 활용합니다. 밀도 RGB-D SLAM은 이 분야의 킬러 앱이었습니다: KinectFusion과 같은 파이프라인의 모든 단계 — 픽셀별 깊이 필터링, 복셀별 TSDF 융합, 픽셀별 레이캐스팅 — 는 픽셀 또는 복셀에 대한 병렬화가 극히 쉬운 (embarrassingly parallel) 매핑 연산이며, 이는 정확히 GPU가 잘하는 일입니다. 30,Hz의 실시간 밀도 SLAM은 CPU에서는 사실상 불가능하며, 이러한 루프를 GPU로 옮긴 순간에야 비로소 가능해졌습니다.
CUDA 개요
CUDA(NVIDIA의 GPGPU 플랫폼)는 GPU를 동일한 커널 함수를 실행하는 경량 스레드들의 그리드로 노출합니다:
- 스레드 계층: 스레드는 블록으로 묶이고, 블록은 다시 그리드로 묶입니다. 픽셀별 커널은 보통 픽셀당 하나의 스레드로 실행되며, 각 스레드는 자신의 블록/스레드 인덱스로부터 자신의 좌표를 계산합니다.
- 메모리 계층: 용량은 크지만 지연 시간이 높은 전역 메모리(global memory), 블록 내 데이터 재사용을 위한 빠른 블록 단위 공유 메모리(shared memory), 그리고 스레드별 레지스터가 있습니다. 성능은 코얼레스드(coalesced) 전역 메모리 접근(인접 스레드가 인접 주소를 읽는 것 — 이미지에서는 자연스럽게 발생)과, PCIe 버스를 거치는 호스트-디바이스(CPU-GPU) 전송을 최소화하는 데 좌우됩니다.
- 실행 모델: 스레드는 락스텝 그룹(워프) 단위로 실행됩니다. 워프 내에서 분기가 갈리면 직렬화되므로, 픽셀별 코드는 무거운 분기를 피해야 합니다.
전형적인 SLAM 커널로는 깊이 맵의 이중선형 필터링, 깊이로부터 정점/법선 맵 계산, TSDF 통합(카메라 절두체 내 복셀마다 하나의 스레드가 해당 복셀을 깊이 이미지에 투영하여 가중 이동 평균을 갱신), 그리고 프레임-대-모델 추적을 위한 TSDF 레이캐스팅이 있습니다.
**병렬 리덕션(parallel reduction)**은 또 하나의 핵심 패턴입니다: 투영 데이터 연관 ICP는 수십만 개의 픽셀에 걸쳐 픽셀별 항 와 를 합산하여 가우스-뉴턴 시스템을 계산합니다. 각 스레드는 자신의 지역 곱을 계산하고, 공유 메모리에서의 트리 구조 리덕션이 블록 단위로 이를 합산하며, 마지막 단계(또는 원자적 연산)가 블록 결과들을 결합합니다. CPU로 복사되는 것은 오직 이 작은 시스템뿐이며, 여기서 풀이가 이루어집니다.
연산 도구로서의 OpenGL GLSL
CUDA 이전과 그와 병행하여, GPGPU는 그래픽 파이프라인을 통해 GLSL 셰이더로 수행되었으며, 여러 영향력 있는 RGB-D 시스템(특히 ElasticFusion)이 이 방식으로 작성되었습니다 — CUDA와 달리 벤더 중립적이라는 장점도 있습니다:
- 데이터는 텍스처와 정점 버퍼에 저장되며, 연산은 프래그먼트 셰이더가 출력 픽셀마다 한 번씩 실행되는 렌더링 패스로 표현되어, 결과를 오프스크린 프레임버퍼 객체(“텍스처로 렌더링”)에 기록하고, 여러 패스에 걸쳐 두 버퍼 사이를 핑퐁하는 경우가 많습니다.
- 서펠 맵은 이 파이프라인에 자연스럽게 들어맞습니다: 각 서펠(위치, 법선, 반지름, 색상, 가중치)이 하나의 정점이며, 맵을 인덱스/모델 이미지로 스플래팅하는 것은 단순한 렌더링이고, 서펠 융합과 컬링은 이 버퍼들에 대한 셰이더 패스로 실행됩니다.
- 최신 OpenGL은 컴퓨트 셰이더도 제공하여 GL 생태계를 벗어나지 않고도 CUDA와의 격차를 대부분 좁혀주며, CUDA-OpenGL 상호운용은 CUDA 커널이 GL 버퍼에 직접 기록하도록 하여 복사 없는(zero-copy) 시각화를 가능하게 합니다.
실무 지침
- 파이프라인 전체를 GPU에 상주시키고, 프레임마다 포즈와 작은 행렬만 다운로드하십시오. 매 프레임 전체 이미지나 볼륨을 호스트-디바이스로 복사하면 가속 효과가 사라집니다.
- 먼저 메모리 트래픽을 프로파일링하십시오 — 대부분의 이미지/복셀 커널은 연산량이 아니라 대역폭에 의해 제한됩니다. 인접 픽셀을 재사용하는 스텐실 형태의 커널(이중선형 필터, 법선 계산)에는 공유 메모리를 사용하십시오.
- GPU에서 이미지 피라미드를 사용하십시오: 거칠기-에서-세밀도 ICP/추적은 동일한 커널을 여러 해상도에서 실행하여 낮은 비용으로 넓은 수렴 영역을 확보합니다.
- 수치 정밀도에 주의하십시오: 일반 소비자용 GPU는
float에서double보다 훨씬 빠릅니다. 밀도 SLAM 파이프라인은 거의 전부 단정밀도로 실행되며, 배정밀도는 그것이 중요한 CPU 측 솔버를 위해 남겨둡니다. - 전통적인 밀도 SLAM을 넘어, 동일한 기술이 스테레오 기반 깊이 추정 신경망, 뉴럴 필드 매핑, 그리고 모든 학습 기반 프론트엔드를 뒷받침합니다: CUDA는 이 모든 것의 기반입니다.
SLAM에서의 의미
- KinectFusion(CUDA)과 ElasticFusion(GLSL)은 두 가지 GPGPU 경로를 보여주며, 둘 다 이해하면 거의 모든 밀도 RGB-D SLAM 코드베이스를 읽고 수정할 수 있습니다.
- GPU/CPU 분할은 아키텍처적 결정입니다: GPU에서 밀도 추적과 매핑, CPU에서 희소 최적화(포즈 그래프, BA)를 수행하는 것이 표준적인 작업 분배입니다.
- 복셀 해싱, TSDF 통합, 레이캐스팅은 GPU 병렬성 덕분에야 실시간이 되었습니다 — 이 영역에서는 알고리즘 설계와 GPGPU 구현이 분리될 수 없습니다.