yuchi's Development Home
2010년에 회사 관두고 여름 내내 한 짓거리가 CUDA 가지고 Ambient Occlusion을 굽는 일이었습니다.
마침 친구의 그래픽 카드 하나를 빌릴 수 있어서 그래픽 카드를 두개 꽂고 CUDA 로컬 디버깅을 적용했습니다.
별로 어렵지 않습니다만 빌린 그래픽 카드를 갖다주고나면 세팅 방법을 잊어버릴것 같아서 기록으로 남겨둡니다. 혹은 CUDA 로컬 디버깅을 고려하고 있는 어느 누군가에게 도움이 될지도 모르겠네요.
[Parallel Nsight 소개]
초기에 CUDA가 발표되었을땐 딱히 디버깅 방법이 없었습니다. CPU코드가 아니다보니 printf()를 이용한 로그조차 사용할 길이 없었죠.
이후에 VS2008,VS2010에 인티그레이션 해서 네이티브 디버깅이 가능한 툴이 제공되었는데 이게 Parallel NSight입니다.
CUDA 디버깅 == Parallel NSight를 이용한 디버깅 입니다.
[CUDA 로컬 디버깅을 위한 요구사항]
GTX295, GTX590등의 듀얼 GPU그래픽 카드 (반드시 SLI기능을 정지시켜야 합니다)
CUDA를 지원하는 nVidia 그래픽 카드 2개
CUDA를 지원하는 Nvidia 그래픽 카드 1개와 CUDA를 지원하지 않는 그래픽 카드 1개
[로컬 디버깅에 GPU가 2개 필요한 이유]
현재 GPU는 CPU와 같은 멀티태스킹을 지원하지 않습니다. 따라서 CUDA코드에 브레이크 포인트를 찍어서 GPU가 블럭되어버리면 GPU가 해야할 다른 일들을 전혀 처리하지 못합니다.
GPU 1개로 로컬디버깅을 시도할 경우 CUDA코드의 브레이크 포인트에서 GPU가 블럭되고 그 순간부터 시스템의 디스플레이는 완전 마비됩니다. 커널은 살아있지만 그래픽 드라이버가 응답하지 않으므로 실상 거의 아무것도 못합니다.
Windows VISTA/7은 그래픽 드라이버가 일정시간 응답하지 않을 경우 자동으로 드라이버를 복구합니다. 그러나 CUDA디버깅 시에는 이마저 사용할 수 없습니다. 브레이크 포인트가 걸리고나면 해당 GPU는 응답할 수 없기 때문에 이 기능을 꺼야합니다.
그래서 싱글 GPU로 CUDA 로컬 디버깅을 하게 되면 시스템이 마비되는 현상으로 이어지는 것입니다.
해결책으로 두개의 GPU를 사용하여 하나는 디스플레이용 , 하나는 CUDA를 돌리기 위한 전용 GPU로 설정합니다.
혹은 PC두대를 네트워크로 연결하여 리모트 디버깅을 해야합니다.
[CUDA 다운로드]
nVidia홈피에서 CUDA sdk와 toolkit을 다운로드 합니다.
http://developer.nvidia.com/cuda-downloads
다음의 4개의 파일만 받으면 됩니다.
[개발자용 드라이버의 설치]
드라이버는 일단 최신 버젼을 사용하도록 하고 문제가 생길 경우 개발자용 드라이버를 받아서 설치합니다.
대개의 경우는 최신 버젼의 드라이버로 잘 작동하지만 다음과 같은 에러를 출력하며 커널 런칭에 실패할 수 있습니다.
Parallel Nsight Debug
CUDA grid launch failed: CUcontext: 2059192 CUmodule: 348912936 Function: _Z9matrixMulILi32EEvPfS0_S0_ii
……
……
지금껏 개발자용 드라이버를 사용하지 않고서도 디버깅을 잘 해왔는데 285.xx버젼의드라이버에서는 문제가 되는 것을 확인했습니다. 유사한 문제는 다음의 링크에서 이슈가 되어있습니다.
http://stackoverflow.com/questions/7791826/cuda-nvidia-nsight-debugging-cuda-grid-launch-failed
[CUDA Toolkit 및 SDK설치]
설치가 뭐 별거 아니지만서도...CUDA코드 작성하거나 디버깅 할때는 설치 경로가 중요합니다. 컴파일할때 폴더 설정해줘야하는게 엄청 귀찮기도 하고 Parallel NSight는 임의로 설치폴더를 바꾸면 제대로 작동하지 않습니다.
4개의 파일을 받았으면 설치해줍니다.
설치해보면 각 파일들이 완전 지 멋대로 전혀 다른 폴더들을 기본 설치 폴더로 지정합니다. 그렇게 되면 관리하기 귀찮으므로 폴더를 따로 지정해주는 것이 좋습니다.(단 Parallel NSight는 폴더를 절대 변경하면 안됩니다.)
제 경우는 다음과 같이 설치했습니다.
GPU Computing SDK -> C:\Program Files\NVIDIA GPU Computing SDK 4.0
CUDA ToolKit -> C:\Program Files\NVIDIA GPU Computing Toolkit
그리고 Parallel NSight는 디폴트 폴더로 지정된 그대로 설치합니다. 경로를 바꿔주면 Visual Studio에서 제대로 인티그레이션 되지 않습니다.
[Build Customization BUF FIX Update의 설치]
Parallel NSight를 설치하고나면 .cu파일을 Visual Studio에 드래드앤드롭 할때 자동으로 Build Customization설정을 해줍니다. 단 현재 버젼에서 버그가 있어 버그 픽스가 같이 배포되고 있습니다.
CUDA4_0BuildCustomizationFix.zip 파일의 압축을 풀고 안에 있는 파일들을 C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0 폴더에 카피해 줍니다.
[설치후 읽어야 할 문서파일]
설치 후에 Parallel NSight링크 폴더를 보면 User Guide가 있는데 반드시 읽어봐야합니다.
사실 여기서 설명하는 내용이 다 나옵니다. 문서를 충분히 읽는다면 이 게시물을 더 이상 읽을 필요는 없을것입니다.
저와 같은 폴더경로에 설치했다면 다음의 위치에 있습니다. 참고로 크롬에선 제대로 출력되지 않으므로 익스플로러에서 읽어야합니다.
C:\Program Files (x86)\NVIDIA Parallel Nsight 2.0\Help\HTML\User Guide.1033_en_US\webframe.html
[TDR끄기]
Timeout Detection and Recovery 이라고 하는 녀석으로 드라이버가 일정 시간 이상 응답하지 않을 경우 자동으로 드라이버를 복구하는 기능입니다. win vista/7은 이 기능이 enable되어있는데 이 상태로는 cuda디버깅을 할 수 없습니다. 따라서 이 기능을 끕니다.
1. 윈도우의 시작메뉴 > NVIDIA Parallel NSight 2.0 > Nsight Monitor를 실행합니다.
2. 시스템 트레이에 NSight Monitor의 아이콘이 나타나면 오른쪽 버튼으로 클릭합니다.
3. Options를 선택합니다.
4. NSight Monitor Option을 클릭합니다.
5. WDDM TDR Enabled를 False로 바꿔줍니다.
6. 리부팅합니다.
[WPF가속 끄기]
Windows Presentation Foundation 의 D3D가속을 끕니다.
1. 탐색기를 엽니다.
2. 32비트 시스템이라면
C:\Program Files\NVIDIA Parallel Nsight 2.0\Common
64비트 시스템이라면
C:\Program Files (x86)\NVIDIA Parallel Nsight 2.0\Common
폴더에서 DisableWpfHardwareAcceleration.reg을 찾아 더블클릭합니다.
해당 키는 HKEY_CURRENT_USER\SOFTWARE\Microsoft\Avalon.Graphics 이며 디폴트로는 존재하지 않습니다. DWORD value = 1은 가속안함 DWORD value = 0은 가속 입니다.
참고로 WPF 하드웨어 가속을 끄고나면 VS2010을 사용할때 가끔씩 코드창이 덜그럭 거리는 일이 생깁니다. 저만 그런지 모르겠지만 다시 하드웨어 가속을 활성화시켜주자 그런 현상이 사라졌습니다.
3. 리부팅합니다.
[AERO 끄기]
CUDA 로컬디버깅을 하려면 win7의 아름다운 UI는 쓸 수 없습니다.
GPU가속을 사용하는 화려한 UI를 꺼야합니다.
최적 퍼포먼스로 맞추면 됩니다. 아니면 다음과 같은 정도로 설정해도 됩니다.
여기까지 했다면 기본적인 구성은 마친것입니다.
[샘플 코드를 이용한 브레이크 포인트 테스트]
VS2010에서 다음의 프로젝트를 로드합니다.
C:\Program Files\NVIDIA GPU Computing SDK 4.0\C\src\matrixMul\matrixMul_vs2010.sln
CUDA강좌가 아닌 디버깅 테스트 강좌이므로 코드 설명은 생략합니다.
1. NSight Monitor를 켭니다.
2. 위에서 설명한대로 설정했다면(정확히는 이것저것 다 껐다면) 다음과 같이 나타납니다.
3.NSight Monitor의 security설정이 다음과 같은지 확인합니다. Secure Server는 사용하지 않는 것으로 합니다.
4. VS2010프로젝트에서의 설정
Parallel NSight를 제대로 설치했다면 VS2010의 메뉴에 NSight메뉴가 보일것입니다. 만약 보이지 않는다면 Parallel NSight를 설치할때 폴더를 변경한 것이므로 삭제하고 기본 지정 폴더로 다시 설치합니다.
NSight->Options 다이얼로그를 열어서 Security항목의 Enable secure connection을 FALSE로 설정합니다.
5. matrixMul프로젝트를 선택하고 프로젝트 설정->NSight User Properties를 엽니다.
다음과 같이 설정되어있는지 확인합니다. 이 다이얼로그는 VS의 프로젝트 설정의 디버깅 다이얼로그와 같습니다. 디버깅을 위해서 런칭할 어플리케이션과 작업폴더, 전달 인수를 설정합니다.
작업중인 CUDA코드가 DLL프로젝트라면 Launch external program에서 런칭할 exe를 지정할 수 있습니다. Connection name는 로컬디버깅의 경우 localhost가 들어가지만 리모트 디버깅이라면 원격 타겟머신의 windows NETBIOS이름이 됩니다.
6. 브레이크 포인트 설정
다음과 같이 코드에 브레이크 포인트를 찍습니다.
7. Start Debugging
Debug -> Start Debugging을 하면 안됩니다. F5를 누르면 안됩니다.
다음과 같이 Nsight메뉴에서 Start CUDA Debugging을 클릭합니다.
8. 값 확인
다음과 같이 브레이크 포인트에서 코드 흐름이 정지합니다.
watch창에서 변수를 확인할 수 있고 GPU코드의 어셈블리 코드를 볼 수도 있습니다.
메뉴에서 NSight -> Windows -> CUDA Debug Focus... 를 선택하면 블럭과 스레드 인덱스로 포커스를 설정할 수 있습니다.
정상적인 프로그래머라면 여기까지 진행했다면 이후 디버깅 작업을 진행할 수 있을 것입니다.
글 작성을 마쳤으므로 저도 이제 그래픽카드를 뽑아서 친구에게 돌려 줄 수 있겠네요.
그럼..