1:核函数
CUDA核函数(Kernel)是用于在GPU上并行执行的函数。CUDA核函数使用__global__关键字进行声明,并使用cudaLaunch或cudaConfigureCall等函数在GPU上执行。
核函数可以由多个线程并行执行,每个线程处理不同的数据部分。通过将数据分解为多个块并在GPU上并行处理它们,可以显著加速计算密集型任务。
在CUDA核函数中,可以使用共享内存来加速线程之间的通信和数据传输。共享内存是每个线程块私有的一块内存,允许线程在块内共享数据。通过减少线程之间的数据传输和同步开销,可以提高程序的性能。
除了共享内存外,CUDA核函数还可以使用其他的GPU资源,如常量内存和纹理内存等。这些资源根据其用途提供了不同的优化选项和性能特性。
总之,CUDA核函数是用于在GPU上并行执行计算的函数,通过使用共享内存和其他GPU资源,可以显著加速计算密集型任务。
注意事项:
1、核函数只能访问GPU内存
2、核函数不能使用变长参数
3、核函数不能使用静态变量
4、核函数不能使用函数指针
5、核函数具有异步性
在CUDA编程中,global 是一个关键字,用于声明一个函数为设备上的核函数。
当你在CUDA C/C++中定义一个函数,并使用 global 关键字标记它时,这个函数就可以从主机代码中被调用,并在GPU上执行。
以下是一个简单的例子:
__global__ void add(int *a, int *b, int *c) {
int index = threadIdx.x + blockIdx.x * blockDim.x;
if (index < N) {
c[index] = a[index] + b[index];
}
}
在这个例子中,add 函数是一个核函数,可以在GPU上并行执行。当它被调用时,它会将两个数组 a 和 b 的元素相加,并将结果存储在数组 c 中。注意这里使用了一些CUDA编程的概念,如线程索引和块索引,用于确定每个线程应该执行的计算任务。
核函数必要条件:__global__修饰 且返回值必须是void
不支持c++ iostream
2:cudaDeviceSynchronize()
cudaDeviceSynchronize 是 CUDA 编程中的一个函数,用于确保在 GPU 上执行的并行线程块完成其操作。
换句话说,这个函数会阻塞主机代码的执行,直到所有在 GPU 上启动的并行线程块都完成。
当你在 CUDA 程序中调用一个核函数(kernel)时,这个核函数会在 GPU 上由多个线程并行执行。由于这些线程是并行执行的,你不能简单地假设一个核函数已经完成,除非你明确地同步它们。这就是 cudaDeviceSynchronize 的用途。
简单地说,如果你在一个核函数之后调用了 cudaDeviceSynchronize,那么在继续执行主机代码之前,它会等待该核函数完成。
例如:
__global__ void myKernel(/* parameters */) {
// ... kernel code ...
}
int main() {
// ... setup code ...
myKernel<<<blocks, threads>>>(/* arguments */);
cudaDeviceSynchronize(); // 等待核函数完成
// 继续执行主机代码...
}
值得注意的是,虽然 cudaDeviceSynchronize() 可以确保核函数完成,但它也会增加一定的执行时间,因为它会等待所有并行线程块完成。因此,在实际应用中,你可能需要仔细考虑何时以及是否需要使用它,以避免不必要的延迟。
例子:
#include<stdio.h>
__global__ void hello_from_gpu()
{
printf("Hello\n");
}
int main(void)
{
hello_from_gpu<<<2,2>>>(); //开辟两个线程块 每个线程块有两个线程
cudaDeviceSynchronize();
return 0;
}
编译运行
wcx@wcx:~/Desktop/CUDATest$ nvcc hello.cu -o hello
wcx@wcx:~/Desktop/CUDATest$ ./hello
Hello
Hello
Hello
Hello