关于CUDA
相关知识点很多,本篇只是初识CUDA
的第一篇介绍。先谈谈为什么CUDA
出现以及为什么需要使用CUDA
。
1 为什么CUDA
出现?
其实CUDA
的出现主要是当下很多算法的算力需求(例如:AI等)无法有效的在CPU
上面满足,所以GPU
应需而生。伴随着GPU
的出现而产生的CUDA
库,能够有效的加速算法执行效率。
- 2 为什么使用
CUDA
?
目前出现的并行计算库不只有CUDA
,包括:OpenCL
、OpenMP
、Sycl
等。但是CUDA
依托于NVIDIA
开发的高层抽象库,更加容易学习同时NVIDIA
提供的Tutorials
更加完善。
使用CUDA并行编程GPU输出Hello World
我们学习C/C++
时候第一行代码基本上也是Hello World
,所以针对CUDA
的并行编程我们也看下面的并行输出。
#include "../common/common.h"
#include <stdio.h>
/*
* A simple introduction to programming in CUDA. This program prints "Hello
* World from GPU! from 10 CUDA threads running on the GPU.
*/
__global__ void helloFromGPU()
{
printf("Hello World from GPU!\n");
}
int main(int argc, char **argv)
{
printf("Hello World from CPU!\n");
helloFromGPU<<<1, 10>>>();
CHECK(cudaDeviceReset());
return 0;
}
下面我们简单分析一下上面的程序:上面的代码与我们平常最常见的串行编程基本类似,只是有些小的区别:
- 修饰符
__global__
告诉编译器,这个函数将会从CPU
中调用,然后在GPU
上执行; - 核函数
helloFromGPU
在main
中有3个尖括号,代表从主线程到GPU
设备端的代码调用; - 最终结果会输出10次
Hello World from GPU
代表执行了10次的核函数运算。
其中宏CHECK
为检查是否有效运行,该函数放在头文件common.h
里面。
#define CHECK(call) \
{ \
const cudaError_t error = call; \
if (error != cudaSuccess) \
{ \
fprintf(stderr, "Error: %s:%d, ", __FILE__, __LINE__); \
fprintf(stderr, "code: %d, reason: %s\n", error, \
cudaGetErrorString(error)); \
} \
}
小结
本篇博客小结:对CUDA
编程有个概念性的认识,如果你学过C++
多线程编程的知识,想必能够有一定理解CUDA
异构编程的理论,核函数类似于C++
中创建多个线程来进行执行的操作。下面我们简单总结一下CUDA
编程的结构步骤:
- 分配
GPU
内存; - 从
CPU
内存中拷贝数据到GPU
内存; - 调用
CUDA
核函数来完成程序指定的运算; - 将数据从
GPU
拷回CPU
内存; - 释放
GPU
内存空间;
上述我们的第一个CUDA
代码,只涉及上述步骤的第三步,后续我们会演示更加完整的CUDA
编程核函数。
NVIDIA官方网站CUDA C编程权威指南