CUDA_基础

CUDA编程形式

 

主函数                        接口函数                     内核函数

 

主函数调用接口函数,接口函数需要的形参在主函数中声明分配内存空间(malloc())、赋好值,调用完毕释放参数内存(free())。

 

接口函数调用内核函数(__global void kernel(参数)),内核函数需要用到的形参在接口函数中声明分配显存空间(cudaMalloc()),将数据复制到显存(cudaMemcpy),调用内核(设置好线程块数量,线程数量),计算结果从显存复制回主机,释放参数内存(cudaFree())。

 

Hello World

将CPU以及系统的内存称为主机,将GPU及其内存称为设备,在GPU设备上执行的函数通常称为核函数(Kernel);

核函数编写规则:带有修饰符__global__;

#include <iostream>
__global__ void kernel(void)
{
}

这个修饰符主要作用是告诉编译器,函数应该编译为在设备而不是主机上运行,在这个例子中,函数kernel()将被交给编译设备代码的编译器,而main()函数将被交给主机编译器

核函数调用规则:带有修饰字符<<<1,1>>>;

参数传递

 1 #include <iostream>
 2 #include "book.h"
 3 {
 4 int main()
 5 {
 6 int c;
 7 int *dev_c;
 8 HANDLE_ERROR(cudaMalloc((void **)&dev_c,sizeof(int)));
 9 add<<<1,1>>>(2,7,dev_c);
10 HANDLE_ERROR(cudaMemcpy(&c,dev_c,sizeof(int),cudaMemcpyDeviceToHost));
11 printf("2+7=%d\n",c);
12 cudaFree(dev_c);
13 return 0;
14 }
15 }
16 
17 __global__ void add(int a,int b,int *c)
18 {
19 *c=a+b;
20 }
View Code

 

 尖括号表示要将一些参数传递给运行时系统,这些参数并不是传递给设备代码的参数,而是告诉运行时如何启动设备代码。

1 int main(void)
2 {
3 kernel<<<1,1>>>();
4 printf("Hello World\n");
5 return 0;
6 }
View Code

当设备执行任何有用的操作时,都需要分配内存;

cudaMalloc()分配内存:作用是告诉CUDA运行时在设备上分配内存,第一个参数是一个指针,指向用于保存新分配内存地址的变量,第二参数是分配内存的大小。

设备指针的使用限制总结如下

可以将cudaMalloc()分配的指针传递给设备上执行的函数;可以在设备代码中使用cudaMalloc()分配的指针进行内存的读/写操作;

可以将cudaMalloc()分配的指针传递给在主机上执行的函数;不能在主机代码中使用cudaMalloc()分配的指针进行内存的读/写操作。

简明之,主机指针只能访问主机代码中的内存,设备指针只能访问设备代码中的内存。

cudaMemcpy()函数:其最后一个参数来指定设备内存指针究竟是源指针还是目标指针。

设备的使用

通过调用cudaGetDeviceCount()获得CUDA设备的数量,然后对每个设备进行迭代并查询各个设备的相关信息,但此种迭代操作执行起来过于繁琐,因此提供了一种自动方式来执行这个迭代操作。

(1)找出我们希望设备拥有的属性并将这些属性填充到一个cudaDeviceProp结构;

(2)将其传递给cudaChooseDevice()函数;

(3)cudaChooseDevice()函数返回一个设备ID,可将这个ID传递给cudaSetDevice(),随后,所有的设备操作都将在这个设备上执行。

 1 cudaDeviceProp prop;
 2 int dev;
 3 HANDLE_ERROR(cudaGetDevice(&dev));
 4 printf("ID of current CUDA device: %d\n",dev);
 5 //属性填充
 6 memset(&prop,0,sizeof(cudaDeviceProp));
 7 prop.major=1;
 8 prop.minor=3;
 9 //设备是否满足条件
10 HANDLE_ERROR(cudaChooseDevice(&dev,&prop));
11 printf("ID of CUDA device closest to revision 1.3: %d\n",dev);
12 HANDLE_ERROR(cudaSetDevice(dev));
View Code

首先我看了讲解CUDA基础部分以后,大致对CUDA的基本了解如下:

第一:CUDA实行并行化的过程分为两部分,一个是线程块之间的并行(这是在每个线程网格中grid进行的),一个是对于每一个线程块内部各线程之间的并行化(每个block内部);

第二:CUDA程序编写的流程:

分为主机端的程序(CPU)与设备端的程序(GPU)

主机端:

初始化GPU→数据准备工作→为输入输出参数分配显存空间→将输入参数从主机端复制到显存→内核启动设置→将输出参数复制到显存空间→释放在设备端分配的显存空间

数据准备工作:这里的数据指的是待放入GPU上执行的计算任务

在显存中可以分配的空间有两种:线性存储器和CUDA数组

将输入参数从主机端复制到显存:执行cudaMemcpyHostToDevice

将输出参数复制到显存空间:执行cudaMemcpyDeviceToHost

内核启动设置:调用内核函数kernelFunc<<<N,M>>>(d_a,d_b,d_c)     N表示执行一个grid中有多少个并行block块,M表示执行一个block中有多少个并行线程(thread)

 CUDA在医学图像上的应用

 提前发现乳腺癌:

超声波成像技术与乳房X线照片结合使用,以辅助乳腺癌的治疗与诊断,受到常规的乳房超声波技术的局限性影响,已经研发了TechniScan医疗系统,其采用了一种三维的超声波成像方法(该方法由于计算量的限制而无法投入实际应用)。简而言之,在将采集到的超声波数据转换为3D图像时需要执行非常耗时的计算,因此使得该项技术无法投入实际应用。

 CUDA计算流体力学及环境科学方面的应用

未完待续。。。

posted @ 2019-06-15 23:40  yabiyabi~  阅读(292)  评论(1编辑  收藏  举报