目录
引子
上文介绍了CUDA的软硬件架构,那回归到编程上来,CUDA这样一个支持CPU/GPU异构编程的框架的运作模式是怎样的呢?本节就来针对性讲一下,
正文
首先明确GPU主板(显卡)和CPU主板其实是两个独立的硬件,而且这系列里所写的CUDA编程也是基于独立显卡。
显卡和GPU的区别:(显卡是带有GPU的主板) Much like a motherboard contains a CPU, a graphics card refers to an add-in board that incorporates the GPU. This board also includes the raft of components required to both allow the GPU to function and connect to the rest of the system.
编程模型总览:CPU作为整体程序的主控机,GPU作为程序中部分计算的加速设备。对数据的处理的套路为:
- CPU申请内存(内存),存入待处理数据A1空间;CPU申请内存(内存),为存放处理好之后的数B1空间;
- GPU申请内存(显存),为待处理的数据腾出空间A;GPU申请内存(显存),为存放处理好之后的数据B空间;cudaMalloc()
- 将CPU上的数据,拷贝到第二步GPU申请的内存空间中;
- 根据数据设定Grid,Block大小,确定GPU处理时的模式;
- 在GPU上执行处理函数(kernel函数),对数据进行处理,并将处理好的数据存放在B空间;
- 将处理好的结果B拷贝到CPU内存空间B1,即处理好的数据重新交回CPU主控单元进行下一步操作;
至此,一个简单的处理逻辑就完成了!
结合代码例子
/****gpu_helloworld.cu****/
#include "device.cu"
#include "kernel.cu"
#include "cstring"
void helloworld(char *str1, char *str2)
{
InitCUDA();
char *dev_str1=0, *dev_str2=0;
int size = strlen(str1) + 1;
cudaMalloc((void**)&dev_str1, size); /*cuda系函数必须放在cu文件里*/
cudaMalloc((void**)&dev_str2, size);
cudaMemcpy(dev_str1, str1, size,cudaMemcpyHostToDevice);
cudaStrcpy<<<1,1>>>(dev_str2, dev_str1); /*单线程块、单线程*/
cudaMemcpy(str2, dev_str1, size, cudaMemcpyDeviceToHost);
}
/****main.cpp****/
#include "cstdio"
#include "cstring"
extern void helloworld(char *str1, char *str2);
int main()
{
char src[] = "HelloWorld with CUDA";
char *des = new char[strlen(src)+1];
helloworld(src, des);
printf("%s\n", des);
}
后续知识点也会围绕CUDA的程序优化展开。(学习总纲)
CUDA编程的难点:/********************※**********************/
- 成千上万个并行线程的任务分配和工作协同。
- 拷入GPU的内存也有讲究,(这里举例:GPU中常用的内存分为全局内存和共享内存,如何利用共享内存更快速的优化计算。)
- CUDA多流执行的分配,粗细粒度的并行安排和分配;(私以为,粗粒度基于GPU和CPU是两个独立的设备,细粒度基于GPU中每个处理核相互独立)
官方补:一次GPU可以申请到的最大内存=(显存空间-0.5G)/2