Main Content

이 번역 페이지는 최신 내용을 담고 있지 않습니다. 최신 내용을 영문으로 보려면 여기를 클릭하십시오.

CUDA 코드가 포함된 MEX 함수 실행하기

CUDA 코드가 포함된 MEX 파일 작성하기

다른 MEX 파일과 마찬가지로 CUDA® 코드를 포함하는 MEX 파일에는 mexFunction이라는 단일 진입점이 있습니다. MEX 함수에는 MATLAB®의 gpuArray 객체와 상호 작용하고 CUDA 코드를 시작하는 호스트 쪽 코드가 포함되어 있습니다. MEX 파일의 CUDA 코드는 CUDA 런타임 API를 따라야 합니다.

MEX 파일에 대한 진입점에서 함수 mxInitGPU를 호출해야 합니다. 이렇게 하면 GPU 장치가 제대로 초기화되고 MATLAB에 인식됩니다.

gpuArray 객체의 MEX 파일 작성에 사용하는 인터페이스는 표준 MATLAB 배열의 MEX 인터페이스와 다릅니다.

다음 파일에서 CUDA 코드가 포함된 MEX 파일의 예제를 확인할 수 있습니다.

이 파일에는 다음 CUDA 장치 함수가 포함되어 있습니다.

void __global__ TimesTwo(double const * const A,
                         double * const B,
                         int const N)
{
    int i = blockDim.x * blockIdx.x + threadIdx.x;
    if (i < N)
        B[i] = 2.0 * A[i];
}

배열 크기를 결정하고 적절한 크기의 그리드를 시작하는 다음 라인도 포함되어 있습니다.

N = (int)(mxGPUGetNumberOfElements(A));
blocksPerGrid = (N + threadsPerBlock - 1) / threadsPerBlock;
TimesTwo<<<blocksPerGrid, threadsPerBlock>>>(d_A, d_B, N);

결과 MEX 함수 실행하기

이 예제에서 MEX 함수는 입력 배열의 모든 요소에 2를 곱하여 출력 배열의 값을 얻습니다. 테스트하려면 모든 요소가 1인 gpuArray를 시작하십시오.

x = ones(4,4,'gpuArray');
y = mexGPUExample(x)
y = 

    2    2    2    2
    2    2    2    2
    2    2    2    2
    2    2    2    2

입력 배열과 출력 배열 모두 gpuArray 객체입니다.

disp(['class(x) = ',class(x),', class(y) = ',class(y)])
class(x) = gpuArray, class(y) = gpuArray

CUDA 커널과의 비교

Parallel Computing Toolbox는 MATLAB과 CUDA 코드를 통합하는 데 사용할 수 있는 CUDAKernel 객체도 지원합니다. MEX 파일을 사용한 접근법과 CUDAKernel을 사용한 접근법 중에서 선택할 때 다음을 고려하십시오.

  • MEX 파일은 NPP(NVIDIA Performance Primitives) 또는 CUFFT 라이브러리 같은 호스트 쪽 라이브러리와 상호 작용할 수 있으며, CUDA 런타임 라이브러리의 함수에 대한 호스트 쪽 호출도 포함할 수 있습니다.

  • MEX 파일은 입력값의 크기를 분석하여 C 코드 또는 C++ 코드와 다른 크기의 메모리를 할당하거나 다른 크기의 그리드를 시작할 수 있습니다. 반면 CUDAKernel 객체를 호출하는 MATLAB 코드는 출력 메모리를 사전할당하고 그리드 크기를 결정해야 합니다.

복소수 데이터에 액세스하기

복소수 데이터는 GPU 장치에서 실수부/허수부 결합형 복소수로 저장됩니다. 즉, 복소수 gpuArray A의 경우 요소 i의 실수부와 허수부는 연속된 주소에 저장됩니다. MATLAB은 장치에 복소수 데이터를 저장할 때 CUDA에 내장된 벡터형을 사용합니다(NVIDIA CUDA C Programming Guide 참조).

커널이 필요로 하는 요건에 따라 포인터를 실수형 또는 내장 벡터형의 복소수 데이터로 형변환할 수 있습니다. 예를 들어, MATLAB에서 다음과 같은 행렬을 만든다고 가정합니다.

a = complex(ones(4,'gpuArray'),ones(4,'gpuArray'));

gpuArray를 MEX 함수에 첫 번째 인수(prhs[0])로 전달하는 경우에는 다음과 같이 호출을 사용하여 복소수 데이터에 대한 포인터를 가져올 수 있습니다.

mxGPUArray const * A = mxGPUCreateFromMxArray(prhs[0]);
mwSize numel_complex = mxGPUGetNumberOfElements(A);
double2 * d_A = (double2 const *)(mxGPUGetDataReadOnly(A));

배열을 길이가 두 배인 실수 배정밀도 배열로 처리하려면 다음 방법으로 수행할 수 있습니다.

mxGPUArray const * A = mxGPUCreateFromMxArray(prhs[0]);
mwSize numel_real =2*mxGPUGetNumberOfElements(A);
double * d_A = (double const *)(mxGPUGetDataReadOnly(A));

GPU에서 복소수 형식과 실수 형식 간에 데이터를 변환하는 함수는 다양하게 있습니다. 이러한 연산에는 데이터를 실수부/허수부 결합형으로 만들기 위해 복사본이 필요합니다. 함수 mxGPUCreateComplexGPUArray는 2개의 실수 mxGPUArray를 가져와 요소들을 실수부/허수부 결합형으로 만들어서 길이가 같은 단일 복소수 mxGPUArray를 생성합니다. 함수 mxGPUCopyRealmxGPUCopyImag는 각각 실수 요소 또는 허수 요소를 새 실수 mxGPUArray로 복사합니다. (mxGPUArray 객체의 경우 mxGetImagData 함수에 상응하는 값이 없습니다.)

GPU MEX 파일 컴파일하기

CUDA 코드를 컴파일하려면 gpuDevice 객체의 ToolkitVersion 속성과 일치하는 버전의 CUDA 툴킷을 설치해야 합니다.

MATLAB에서 mexcuda 명령을 사용하여 CUDA 코드가 포함된 MEX 파일을 컴파일합니다. 다음 명령을 사용하여 예제 파일을 컴파일할 수 있습니다.

mexcuda mexGPUExample.cu

mexcuda가 NVIDIA 컴파일러(nvcc)를 찾을 수 없는 경우 디폴트가 아닌 위치에 설치되었을 수 있습니다. 시스템에서 nvcc의 위치를 환경 변수 MW_NVCC_PATH에 저장하여 지정할 수 있습니다. MATLAB setenv 명령을 사용하여 이 변수를 설정할 수 있습니다. 예를 들면 다음과 같습니다.

setenv('MW_NVCC_PATH','/usr/local/CUDA/bin')

mexcuda의 경우 Visual Studio® 컴파일러의 일부만 지원됩니다. 자세한 내용은 NVIDIA toolkit documentation을 참조하십시오.

관련 항목