CUDA 프로그래밍 - 호스트(Host), 디바이스(Device)
목차
- 호스트(Host), 디바이스(Device)
- CUDA C/C++ 키워드
- 커널의 실행, 실행 구성
안녕하세요. 오늘 글에서는 지난 Hello CUDA 예제에서 설명드리지 못한 CUDA 프로그래밍 키워드와 호스트, 디바이스, 커널 개념에 대해 다루고자 합니다. Hello CUDA 예제를 확인하고 싶으시면 아래의 글을 읽어보시는 것을 추천드립니다.
호스트(Host), 디바이스(Device)
Hello CUDA 예제에서 호스트, 디바이스에 대해 언급했습니다. CUDA, GPU 프로그래밍 관련 문서를 참고하다 보면 호스트(host)와 디바이스(device)라는 용어를 자주 볼 수 있습니다. 호스트는 일반적으로 CPU, 디바이스는 GPU를 지칭합니다.
CPU가 GPU의 최초 모듈을 호출한다는 의미에서 호스트가 된다고 생각하면 됩니다. 따라서, CPU에서 실행하는 코드를 호스트 코드(host code), GPU에서 실행하는 코드를 디바이스 코드(device code)라고 하고, CPU가 사용하는 시스템 메모리를 호스트 메모리(host memory), GPU가 사용하는 메모리를 디바이스 메모리(device memory)라고 합니다.
CUDA 프로그램은 호스트 코드와 디바이스 코드로 구성됩니다. 일반적으로 GPU에서 실행되는 디바이스 코드(커널)는 호스트 코드에서 호출되어야 하기 때문에 호스트 코드가 함께 있어야 합니다. CUDA 프로그램의 호스트 코드는 gcc 또는 비주얼 스튜디오의 컴파일러 등 C/C++ 컴파일러로 컴파일되고, 디바이스 코드는 nvcc 컴파일러로 컴파일됩니다.
CUDA 프로그램을 작성할 때, 일반적으로 .cu, .cuh 확장자명을 사용합니다. C/C++의 .c, .cpp 확장자는 .cu에 대응되고, 헤더 파일에 사용되는 .h, .hpp는 .cuh에 대응됩니다. 다른 확장자를 사용해도 무방하나 일반적으로 사용되는 .cu와 .cuh를 사용하는 것을 권장합니다.
CUDA C/C++ 키워드
CUDA는 C/C++을 확장한 프로그래밍 인터페이스입니다. 이러한 확장을 위해 CUDA C/C++ 키워드(keyword)를 사용합니다. 지난 시간의 Hello CUDA 예제를 보면서 CUDA의 새로운 키워드를 확인해 보도록 하겠습니다. Line 4, 5에 포함한 cuda_runtime.h와 device_launch_parameters.h는 CUDA 런타임 API를 사용하기 위한 헤더 파일입니다. CUDA 프로그래밍에서 런타임 API를 사용하는 경우, 대부분 추가한다고 생각하면 됩니다.
예제 코드에서 대표적으로 확인할 수 있는 CUDA 키워드는 line 8의 __global__과 line 17의 <<<>>>입니다. __global__은 호스트에서 호출하고, 디바이스에서 실행되는 함수임을 지정하는 키워드입니다. 함수의 호출자와 실행 공간을 지정하는 키워드는 아래와 같습니다.
키워드 | 함수의 호출자 | 실행 공간 |
__host__ | host | host |
__device__ | device | device |
__global__ | host | device |
CPU(host)에서 실행되는 코드는 호스트 코드, GPU(device)에서 실행되는 코드는 디바이스 코드입니다. 따라서, __host__와 __device__가 호스트 함수를 나타내고, 키워드를 표시하지 않으면 기본 값은 __host__로 호스트 함수가 됩니다. 호스트 함수는 호스트 코드에서만, 디바이스 함수는 디바이스 코드에서만 호출이 가능합니다. 만약 호스트와 디바이스 모두에서 사용하고 싶다면 __host__ __device__와 같이 두 지시어를 나란히 적어주면 됩니다.
우리가 작성하는 프로그램은 기본적으로 호스트에서 실행됩니다. GPU에서 연산을 수행하고 싶다면 디바이스 코드를 실행해야 하고, 그때 사용하는 키워드가 __global__입니다. __global__로 지정된 함수는 호스트에서 호출하고 디바이스에서 실행되는 함수이며, CUDA에서 이를 커널(kernel)이라고 합니다. 예제코드에서 line 8~10의 HelloCUDA() 함수는 커널함수를 정의하는 부분입니다.
커널의 실행, 실행 구성
커널은 호스트가 디바이스에 연산을 요청하는 통로이고, CUDA 스레드의 동작을 정의하는 함수입니다. 커널 호출 시, 커널을 수행할 CUDA 스레드의 수를 결정해야 합니다. CUDA 스레드 수는 <<<>>> 실행 구성(execution configuration) 문법을 통해 지정합니다. CUDA 스레드는 특정 단위로 그룹을 이루고, 그룹들은 계층적으로 구성되어 있습니다. 해당 계층 구성은 추후 포스팅을 통해 상세히 설명드리도록 하겠습니다.
아래 함수는 10개의 CUDA 스레드가 HelloCUDA() 커널을 수행하라는 의미입니다. HelloCUDA<<<1, 10>>>() 함수를 호출했을 때, "Hello CDUA from GPU!"가 10번 호출된 것을 확인할 수 있습니다. 이는 <<<1, 10>>>과 같이 10개의 스레드가 HelloCUDA() 커널을 실행했기 때문입니다.
마치며
오늘은 지난 포스팅의 Hello CUDA 예제에서 설명드리지 못한 개념에 대해 다루었습니다. 호스트, 디바이스, 커널 개념과 Hello CUDA 예제에서 사용된 기본적인 CUDA 키워드를 소개해 드렸습니다. 이어지는 포스팅에서는 CUDA 프로그램의 구조, 흐름과 CUDA의 기초 메모리 API에 대해 설명드리고자 하니 많은 관심 부탁드립니다!
오늘 포스팅도 도움이 되셨기를 바랍니다. 좋은 하루 보내시길 바랍니다. 고맙습니다.
Reference
1. CUDA 기반 GPU 병렬 처리 프로그래밍 - 기초부터 성능 최적화 전략까지
'Tech Insights' 카테고리의 다른 글
CUDA 프로그래밍 - 기초 메모리 API(2) (0) | 2024.03.10 |
---|---|
CUDA 프로그래밍 - 기초 메모리 API(1) (0) | 2024.03.09 |
CUDA 프로그래밍 - Hello CUDA! (Linux) (0) | 2024.03.02 |
CUDA 프로그래밍 - Hello CUDA! (0) | 2024.03.02 |
CUDA 프로그래밍 - 병렬 처리란? (2) (0) | 2024.02.29 |