关于cuda:何时调用cudadevicesynchronize?
在使用CUDA进行GPU编程时,我们需要了解何时调用cudaDeviceSynchronize()
函数。本文将详细讲解cudaDeviceSynchronize()
函数的作用、使用方法和示例。
cudaDeviceSynchronize()
函数的作用
cudaDeviceSynchronize()
函数用于等待当前设备上所有的任务完成。在CUDA程序中,GPU和CPU是异步执行的,因此在某些情况下,我们需要等待GPU完成任务后再执行CPU的任务。这时,就需要使用cudaDeviceSynchronize()
函数。
cudaDeviceSynchronize()
函数的使用方法
cudaDeviceSynchronize()
函数的使用方法非常简单,只需要在需要等待GPU完成任务的地方调用该函数即可。例如:
kernel<<<gridSize, blockSize>>>(d_data);
cudaDeviceSynchronize();
在上面的示例中,kernel
是一个GPU核函数,gridSize
和blockSize
是启动核函数的网格和块的大小,d_data
是一个在GPU上分配的数据。在调用kernel
函数后,我们需要等待GPU完成任务后再执行后续的CPU任务,因此在kernel
函数后调用了cudaDeviceSynchronize()
函数。
示例1:使用cudaDeviceSynchronize()
函数计算向量加法
以下是使用cudaDeviceSynchronize()
函数计算向量加的示例:
#include <stdio.h>
__global__ void add(int *a, int *b, int *c, int n)
{
int i = threadIdx.x;
if (i < n)
{
c[i] = a[i] + b[i];
}
}
int main()
{
int n = 100000;
int *a, *b, *c;
int *d_a, *d_b, *d_c;
int size = n * sizeof(int);
// 分配内存
cudaMalloc((void **)&d_a, size);
cudaMalloc((void **)&d_b, size);
cudaMalloc((void **)&d_c, size);
a = (int *)malloc(size);
b = (int *)malloc(size);
c = (int *)malloc(size);
// 初始化数据
for (int i = 0; i < n; i++)
{
a[i] = i;
b[i] = i;
}
// 将数据从主机内存复制到设备内存
cudaMemcpy_a, a, size, cudaMemcpyHostToDevice);
cudaMemcpy(d_b, b, size, cudaMemcpyHostToDevice);
// 启动核函数
add<<<1, n>>>(d_a, d_b, d_c, n);
// 等待GPU完成任务
cudaDeviceSynchronize();
// 将数据从设备内存复制到主机内存
cudaMemcpy(c, d_c, size, cudaMemcpyDeviceToHost);
// 输出结果
for (int i = 0; i < n; i++)
{
printf("%d ", c[i]);
}
// 释放内存
cudaFree(d_a);
cudaFree(d_b);
cudaFree(d_c);
free(a);
free(b);
free(c);
return 0;
}
在上面的示例中,使用cudaDeviceSynchronize()
函数等待GPU完成向量加法任务后再将结果从设备内存复制到主机内存并输出。
示例2:使用cudaDeviceSynchronize()
函数计算矩阵乘法
以下是使用cudaDeviceSynchronize()
函数计算矩阵乘法的示例:
#include <stdio.h>
#define N 1024
__global__ void matrixMul(int *a, int *b, int *c)
{
int i = blockIdx.x * blockDim.x + threadIdx.x;
int j = blockIdx.y * blockDim.y + threadIdx.y;
int sum = 0;
if (i < N && j < N)
{
for (int k = 0; k < N; k++)
{
sum += a[i * N + k] * b[k * N + j];
}
c[i * N + j] = sum;
}
}
int main()
{
int *a, *b, *c;
int *d_a, *d_b, *d_c;
int size = N * N * sizeof(int);
// 分配内存
cudaMalloc((void **)&d_a, size);
cudaMalloc((void **)&d_b, size);
cudaMalloc((void **)&d_c, size);
a = (int *)malloc(size);
b = (int *)malloc(size);
c = (int *)malloc(size);
// 初始化数据
for (int i = 0; i < N * N; i++)
{
a[i] = i;
b[i] = i;
}
// 将数据从主机内存复制到设备内存
cudaMemcpy(d_a, a, size, cudaMemcpyHostToDevice);
cudaMemcpy(d_b, b, size, cudaMemcpyHostToDevice);
// 启动核函数
dim3 threadsPerBlock(16, 16);
dim3 numBlocks(N / threadsPerBlock.x, N / threadsPerBlock.y);
matrixMul<<<numBlocks, threadsPerBlock>>>(d_a, d_b, d_c);
// 等待GPU完成任务
cudaDeviceSynchronize();
// 将数据从设备内存复制到主机内存
cudaMemcpy(c, d_c, size, cudaMemcpyDeviceToHost);
// 输出结果
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
printf("%d ", c[i * N + j]);
}
printf("\n");
}
// 释放内存
cudaFree(d_a);
cudaFree(d_b);
cudaFree(d_c);
free(a);
free(b);
free(c);
return 0;
}
在上面的示例中,使用cudaDeviceSynchronize()
函数等待GPU完成矩阵乘法任务后再将结果从设备内存复制到主机内存并输出。
总的来说,cudaDeviceSynchronize()
函数是一个非常有用的函数,可以用于等待GPU完成任务后再执行CPU的任务。通过上述攻略和示例,可以轻松地使用cudaDeviceSynchronize()
函数计算向量加法和矩阵乘法。