CUDA 지원
우분투 13.04에 NVIDIA의 그래픽칩을 사용하는 그래픽카드가 설치되어 있고, NVIDIA의 독점 그래픽 드라이버가 설치 되어 있다고 가정한다. 매스매티카의 도움말을 따르면 이 단계에서 다음의 테스트를 통과해야 한다.
In[1]:= << CUDALink` In[2]:= CUDAQ[] Out[2]= False하지만 실패! 인터넷을 뒤져보니, 이건 매스매티카가 CUDA 라이브러리를 찾지 못해서 발생하는 문제로 환경 변수 설정이 필요한 걸 알 수 있다. 내 경우엔 NVIDIA 그래픽 드라이버 버전이 319.37이므로 이에 해당하는 라이브러리를 찾아 환경변수에 등록해준다.
--- /etc/profile.d/Mathematica.sh.orig 2013-10-09 00:19:53.671638435 +0900 +++ /etc/profile.d/Mathematica.sh 2013-10-09 00:20:15.543638995 +0900 @@ -1,2 +1,4 @@ #!/bin/sh export MATHEMATICA_HOME=/opt/Wolfram/Mathematica/9.0 +export NVIDIA_DRIVER_LIBRARY_PATH=/usr/lib/nvidia-current/libnvidia-tls.so.319.37 +export CUDA_LIBRARY_PATH=/usr/lib/nvidia-current/libcuda.so이제 다시 로그인 한 후에 매스매티카를 실행해보면 위의 테스트를 깔끔히 통과한다.
OpenCL 지원
자신의 NVIDIA 칩이 OpenCL을 지원한다면, 매스매티카의 OpenCL 인터페이스도 사용할 수 있다. 지원 여부는 위키피디아에서 확인할 수 있다.
In[1]:= << OpenCLLink` In[2]:= OpenCLQ[] Out[2]= False역시 실패! 여기에 따르면, 매스매티카가 엉뚱한 위치에서 OpenCL 라이브러리 찾기 때문이다. 더욱이 이 위치는 고정되어 바꿀 수 없다. 따라서 매스매티카가 찾는 위치에 맞추어서 링크를 만들어줘야 한다.
$ sudo mkdir -p /usr/lib64 $ sudo ln -s /usr/lib/nvidia-current/libOpenCL.so /usr/lib64/이제 매스매티카 커널을 재시작하고 위 테스트를 실행해보면, 문제없이 통과!
CUDA 개발환경(Toolkit) 지원 컴파일러
매스매티카에서 제공하는 내장 CUDA 함수는 잘 동작한다. 하지만 외부 CUDA 함수를 매스매티카로 불러오면 gcc 4.7 이상은 지원하지 않는다는 에러가 발생한다.
In[2]:= code = "__global__ void addTwo(mint * in, mint * out, mint length) { int index = threadIdx.x + blockIdx.x*blockDim.x; if (index < length) out[index] = in[index] + 2; }"; In[3]:= cudaFun = CUDAFunctionLoad[code, "addTwo", {{_Integer, _, "Input"}, {_Integer, _, "Output"}, _Integer}, 256] During evaluation of In[3]:= CUDAFunctionLoad::cmperr: -- Message text not found -- (/home/kwchun/.Mathematica/Paclets/Repository/CUDAResources-Lin64-9.0.0.0/CUDAToolkit/bin/../include/host_config.h:82:2: error: #error -- unsupported GNU version! gcc 4.7 and up are not supported!) >> Out[3]= CUDAFunctionLoad["__global__ void addTwo(mint * in, mint * out, mint length) {int index = threadIdx.x + blockIdx.x*blockDim.x; if (index < length) out[index] = in[index] + 2;}", "addTwo", {{_Integer, _, "Input"}, {_Integer, _, "Output"}, _Integer}, 256]에러에 나와 있듯이 2013년 9월 5일 현재 매스매티카의 CUDA 개발환경(Toolkit) 버전은 9.0.0.0이고, 이 버전은 gcc 4.7 이상을 지원하지 않는다. 이 문제는 "XCompilerInstallation" 옵션으로 CUDA 개발환경이 지원하는 C 컴파일러의 경로를 지정하면 해결된다.
In[4]:= cudaFun = CUDAFunctionLoad[code, "addTwo", {{_Integer, _, "Input"}, {_Integer, _, "Output"}, _Integer}, 256, "XCompilerInstallation" -> "/usr/bin/gcc-4.6"] Out[4]= CUDAFunction["<>", "addTwo", {{_Integer, _, "Input"}, {_Integer, _, "Output"}, "Integer64"}]
OpenCL에서 배정도 부동소수점 사용
(아마도) 64비트 환경에서 OpenCL 외장 함수 내에 배정도 부동소수점을 사용하면 아래와 같이 함수를 불러드릴 수 없다.
code = " __kernel void addTwo(__global Real_t *in, __global Real_t *out, mint length) { int index = get_global_id(0); if (index < length) out[index] = in[index] + 2; }"; openclFun = OpenCLFunctionLoad[code, "addTwo", {{_Real, _, "Input"}, {_Real, _, "Output"}, _Real}, 256, "ShellOutputFunction" -> Print ] OpenCLFunctionLoad::cmpf: The kernel compilation failed. Consider setting the option "ShellOutputFunction"->Print to display the compiler error message. >> :2:31: error: must specify '#pragma OPENCL EXTENSION cl_khr_fp64: enable' before using 'double' __kernel void addTwo(__global Real_t *in, __global Real_t *out, mint length) { ^ In file included from <built-in>:17306: <command line>:4:16: note: instantiated from: #define Real_t double ^이건 에러 메시지에도 나와 있듯이, OpenCL 관련 매크로를 코드의 앞부분에 넣어주면 해결된다.
code = " #ifdef USING_DOUBLE_PRECISIONQ #ifdef OPENCLLINK_USING_NVIDIA #pragma OPENCL EXTENSION cl_khr_fp64: enable #else /* OPENCLLINK_USING_NVIDIA */ #pragma OPENCL EXTENSION cl_amd_fp64: enable #endif /* OPENCLLINK_USING_NVIDIA */ #endif /* USING_DOUBLE_PRECISIONQ */ __kernel void addTwo(__global Real_t *in, __global Real_t *out, mint length) { int index = get_global_id(0); if (index < length) out[index] = in[index] + 2; }";