[NVIDIA GPU] Multi-GPUs CUDA 코딩 방법

과제로 CUDA 코딩을 연습하고 있는데 Multi-GPUs를 사용하는 코딩 방법이 크게 2가지 정도 있어 정리하였다. 아래 방법 이외 다른 게 있을 수도 있으나 공부하면서 이해한 방법은 크게 아래의 2가지 정도인 듯하다.

Inter Process Communication (IPC)를 사용한 Multi-GPUs 사용

간단하게 설명하면 1개의 process가 1개의 GPU를 사용한다. 여러 개의 GPU를 사용하기 위해 여러 개의 process를 만들어야 한다.

그림 1: IPC를 사용하여 Multi-GPUs 사용

그림 1이 IPC를 사용하여 Multi-GPUs를 사용하는 방식이다. (처음으로 제가 그린 그림이네요) Parent process가 여러 개의 child process를 생성하고 각 child process는 하나의 GPU를 사용한다. 하나의 child process가 여러 개의 GPU를 사용해도 상관은 없으나 추천하지 않는다고 한다. Parent process가 fork() 또는 CreateThread()와 같은 함수를 사용하여 child process를 생성한다. 각 child process는 cudaSetDevice() 함수를 사용하여 child process가 사용하는 GPU를 선택한다. Parent process가 waitpid()등의 함수를 사용하여 동기화 문제를 해결한다.

IPC 방식은 서로 다른 input set 또는 다른 kernel을 GPU를 사용하여 연산을 수행할 때 효과적인 방법인 것 같다. NVIDIA CUDA sample 코드 중 simpleIPC폴더에 예제 코드를 확인할 수 있다.

 

CUDA API를 사용한 Multi-GPUs 사용

IPC 방식과 달리 1개의 process가 CUDA API를 사용하여 여러 개의 GPU를 사용하여 연산을 수행하는 방식이다.

그림 2: CUDA API를 사용하여 Multi-GPUs 사용

그림 2는 CUDA API를 사용한 Multi-GPUs 연산 방법이다. 하나의 process가 cudaSetDevice(), cudaMemcpyAsynch()등의 함수를 사용하여 여러 개의 GPU에 kernel을 실행한다.

cudaMemcpy대신 cudaMemcpyAsynch 함수를 사용해야 하는 이유는 cudaMemcpyAsynch 의 경우 memory 복사하는 동안 다른 host 코드를 실행할 수 있다. 하지만, cudaMemcpy의 경우 host 코드와 memory 복사가 동시에 실행되지 않아 multi-GPU를 효과적으로 사용할 수 없다. (Multi-GPU의 사용하는 이유가 없어지는 것 같다. cudaMemcpy의 경우 성능 향상이 존재하지 않았다)

이 방식은 하나의 Input data set을 여러 단위로 나누어 Multi-GPU를 사용하여 연산을 수행할 때 효과적인 방법인 것 같다. 각 GPU가 수행해야 하는 연산의 차이가 적을 수록 효과적이다. 물론 다른 kernel을 수행해도 상관은 없는 것 같다. 하지만 어떤 GPU에서 연산이 먼저 종료되었는지 확인하는 방법을 찾지 못하였다. 만약 먼저 연산 끝난 GPU를 알 수 있다면 IPC 방법 대신 CUDA API를 사용하면 더 쉽게 코딩을 할 수 있을 것 같다. NVIDIA CUDA Sample 코드에서 simpleMultiGPU 에 예제 코드를 찾을 수 있다.

출처

  1. https://developer.nvidia.com/cuda-code-samples
  2. http://stackoverflow.com/questions/13743039/about-cudamemcpyasync-function
  3. http://www.nvidia.in/graphics-cards/geforce/pascal/gtx-1080/

Leave a Comment