CUDA를 이용한 복셀 월드의 라이트맵 계산 – 성능개선

엊그제 포스팅했던 CUDA를 이용한 라이트맵 베이킹의 성능향상에 대한 얘기다.

좀더 GPU를 빡시게 사용하려고 cuda Stream + 멀티스레드 까지 적용했는데 생각보단 성능이 많이 오르지 않는다.
프로파일링 해보니 Occupancy가 이론상 50% 달성할 수 있는데 실제로는 29.3%만 달성한 것으로 나온다. Occupancy가 영 만족스럽지 못하다.
31184661_1873827062649030_8411584266852368384_o

그래서 이런저런 튜닝을 좀 했다.
오랫만에 Occupancy Calculator를 실행해서 SM 5.2와 6.1기준으로 숫자를 넣어 Occupancy 예상치를 구했다.

voxel_horizon_2018_0423_occupancy_calc

1. 일단 레지스터 개수를 32개로 맞춰서 이론상 가능한 occupancy를 100%로 올렸다. 이것으로 SM당 한번에 스케쥴링 가능한 warp개수는 2개가 되었다.

2. 실제 커널함수 작동시에 global memory dependency가 문제가 되고 있다. global memory억세스가 많기도 하지만 주된 문제는 stack을 global memory로 구현하고 있기 때문이다.
이 문제를 해결하기 위해 stack으로 사용할 메모리를 shared memory로 바꿨다. 이것으로 Memory dependency는 줄어들 것이다.

3. shared memory는 block당 48KB 제한이 있고 따라서 많이 사용하면 한번에 사용할 수 있는 thread개수가 왕창 줄어든다. 또한 stack메모리 한계에 도달했을 경우 문제가 된다.
그래서 KD-Tree traversal에 semi stack 기법을 적용했다. stack 한계치에 도달해서 더 이상 push할 수 없을 경우 현재 ray의 t값으로 루트 노드부터 다시 탐색한다.
shared memory는 block당 16KB를 할당했다. block당 최대 512 thread를 맵핑할것이므로 thread당 (16384 / 512) =  32 bytes의 stack을 사용할 수 있다.

[결과]
voxel_horizon_2018_0423_nsight_profile

이론상 최대Occupancy(코드 구현상 가능한 최대치) – 100% ,
실제 달성한 Occupancy는 54.87%.

최대 GPU점유율 99%.
라이트맵 베이킹에 걸리는 시간은 이제 2.8초.


답글 남기기

댓글을 게시하려면 다음의 방법 중 하나를 사용하여 로그인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

%s에 연결하는 중