CUDA 并行编程
#include <iostream>
#include <cuda.h>
#include <driver_types.h>
#include <device_launch_parameters.h>
#include "utils.h"
#define N 10
static void HandleError( cudaError_t err,
const char *file,
int line ) {
if (err != cudaSuccess) {
printf( "%s in %s at line %d\n", cudaGetErrorString( err ),
file, line );
exit( EXIT_FAILURE );
}
}
#define HANDLE_ERROR( err ) (HandleError( err, __FILE__, __LINE__ ))
__global__ void add(int *a, int *b, int *c)
{
int tid = blockIdx.x;
if (tid < N)
{
c[tid] = a[tid] + b[tid];
}
}
int main()
{
int a[N], b[N], c[N];
int *dev_a, *dev_b, *dev_c;
HANDLE_ERROR(cudaMalloc( (void**)&dev_a, N * sizeof(int) ) );
HANDLE_ERROR(cudaMalloc( (void**)&dev_b, N * sizeof(int) ) );
HANDLE_ERROR(cudaMalloc( (void**)&dev_c, N * sizeof(int) ) );
for (int i=0; i<N;i++)
{
a[i] = -i;
b[i] = i*i;
}
HANDLE_ERROR(cudaMemcpy(dev_a, a, N * sizeof(int), cudaMemcpyHostToDevice));
HANDLE_ERROR(cudaMemcpy(dev_b, b, N * sizeof(int), cudaMemcpyHostToDevice));
add<<<N, 1>>>(dev_a, dev_b, dev_c);
HANDLE_ERROR(cudaMemcpy(c, dev_c, N* sizeof(int), cudaMemcpyDeviceToHost));
for (int i=0;i<N;i++)
{
printf("%d + %d = %d\n", a[i], b[i], c[i]);
}
cudaFree(dev_a);
cudaFree(dev_b);
cudaFree(dev_c);
return 0;
}
- 调用
cudaMalloc()
在设备上为三个数组分配内存,其中两个数组 dev_a
和dev_b
中包含 输入值,而在数组 dev_c
中包含了计算结果. - 为了鼻尖内存泄露,在使用完 GPU 内存后,通过
cudaFree()
释放内存. - 通过
cudaMemcpy()
将输入 数据复制到设备中,同时指定参数cudaMemcpyHostToDevice
, 在计算完记过,通过参数 cudaMemcpyDeviceToHost
复制回主机. - 通过尖括号语法,在主机代码
main()
中执行 add()
中的设备代码. __global__
修饰符- 我们增看到过通过以下形式启动的核函数
kernel<<<1, 1>>>(param1, param2, ...)
add<<<N, 1>>>(dev_a, dev_b, dev_c)
第一个参数表示设备执行核函数时,使用的并行线程块的数量,指定这个参数为 N
- 为什么不是
blockIdx
, 而是 blockIdx.x
, 事实上因为 CUDA
支持二维的线程块数组,当启动核函数时,我们将并行线程块数量指定 N
, 这个并行线程块集合也成为一个线程格 Grid
, 我们使用的是一维的线程则,第一个线程块的blockIdx.x
=0, 最后一个线程块 blockIdx.x=N-1
. 第二个参数是每个线程块中使用一个线程。