大家一起来学习cuda C (zhuan)
CUDA C不是C语言,而是对C语言进行扩展。
CUDA对C的扩展主要包括以下四个方面: 函数类型限定符,用来确定函数是在CPU还是在GPU上执行,以及这个函数是从CPU调用还是从GPU调用。
__device__,__device__表示从GPU上调用,在GPU上执行;
__global__,__global__表示在CPU上调用,在GPU上执行,也就是所谓的内核(kernel)函数;内核主要用来执行多线程调用。
__host__,__host__表明在CPU上调用,在CPU上执行,这是默认时的情况,也就是传统的C函数。
CUDA支持__host__和__device__的联用,表示同时为主机和设备编译。
此时这个函数不能出现多线程语句。
变量类型限定符,用来规定变量存储什么位置上。
在传统的CPU程序上,这个任务由编译器承担。在CUDA中,不仅要使用主机端的内存,还要使用设备端的显存和GPU片上的寄存器、共享存储器和缓存。
在CUDA存储器模型中,一共抽象出来了8种不同的存储器。复杂的存储器模型使得必须要使用限定符要说明变量的存储位置。
(注意,上面的那个是函数的类型限定,现在这个是变量的限定)
__device__,__device__表明声明的数据存放在显存中,所有的线程都可以访问,而且主机也可以通过运行时库访问;
__shared__,__shared__表示数据存放在共享存储器在,只有在所在的块内的线程可以访问,其它块内的线程不能访问;
__constant__,__constant__表明数据存放在常量存储器中,可以被所有的线程访问,也可以被主机通过运行时库访问;
texture,texture表明其绑定的数据可以被纹理缓存加速存取,其实数据本身的存放位置并没有改变,
纹理是来源于图形学的一介概念,CUDA使用它的原因一部分在于支持图形处理,另一方面也可以利用它的一些特殊功能。
如果在GPU上执行的函数内部的变量没有限定符,那表示它存放在寄存器或者本地存储器中,在寄存器中的数据只归线程所有,其它线程不可见。 如果SM的寄存器用完,那么编译器就会将本应放到寄存器中的变量放到本地存储器中。
执行配置运算符<<< >>>,用来传递内核函数的执行参数。
执行配置有四个参数:
第一个参数声明网格的大小,
第二个参数声明块的大小,
第三个参数声明动态分配的共享存储器大小,默认为0,
最后一个参数声明执行的流,默认为0。
五个内建变量,用于在运行时获得网格和块的尺寸及线程索引等信息 gridDim, gridDim是一个包含三个元素x,y,z的结构体,分别表示网格在x,y,z三个方向上的尺寸,虽然其有三维,但是目前只能使用二维;
blockDim, blockDim也是一个包含三个元素x,y,z的结构体,分别表示块在x,y,z三个方向上的尺寸,对应于执行配置中的第一个参数,对应于执行配置的第二个参数; blockIdx, blockIdx也是一个包含三个元素x,y,z的结构体,分别表示当前线程所在块在网格中x,y,z三个方向上的索引; threadIdx, threadIdx也是一个包含三个元素x,y,z的结构体,分别表示当前线程在其所在块中x,y,z三个方向上的索引;
warpSize,warpSize表明warp的尺寸,在计算能力为1.0的设备中,这个值是24,在1.0以上的设备中,这个值是32。 其它的还有数学函数,原子函数,纹理读取、绑定函数,内建栅栏,内存fence函数等。
一般而言,知道这些就应该能够写出CUDA程序了,当然要写好的话,必须知道很多其它的细节。
因为我对操作系统了解得不是很细,然后下面是补充的一些知识。
这里的内核函数是指,系统调用函数,就是API接口,让处于用户态的我们能够向操作系统发出函数调用请求
线程:
我对于线程,进程的概念一直都是比较模糊,最近整理了一下。总结起来就是,线程是进程的一部分,进程是程序的一部分。
线程的引入:例如,有一个Web服务器要进程的方式并发地处理来自不同用户的网页访问请求的话,可以创建父进程和多个子进程的方式来进行处理,但是创建一个进程要花费较大的系统开销和占用较多的资源。除外,这些不同的用户子进程在执行的时候涉及到进程上下文切换,上下文切换是一个复杂的过程。所以,为了减少进程切换和创建的开销,提高执行效率和节省资源,人们在操作系统中引入了"线程(thread)"的概念。
进程的作用和定义:进程是为了提高CPU的执行效率,减少因为程序等待带来的CPU空转以及其他计算机软硬件资源的浪费而提出来的。进程是为了完成用户任务所需要的程序的一次执行过程和为其分配资源的一个基本单位,是一个具有独立功能的程序段对某个数据集的一次执行活动。
1、线程是进程的一部分,所以线程有的时候被称为是轻权进程或者轻量级进程。
2、一个没有线程的进程是可以被看作单线程的,如果一个进程内拥有多个进程,进程的执行过程不是一条线(线程)的,而是多条线(线程)共同完成的。
3、系统在运行的时候会为每个进程分配不同的内存区域,但是不会为线程分配内存(线程所使用的资源是它所属的进程的资源),线程组只能共享资源。那就是说,出了CPU之外(线程在运行的时候要占用CPU资源),计算机内部的软硬件资源的分配与线程无关,线程只能共享它所属进程的资源。
4、与进程的控制表PCB相似,线程也有自己的控制表TCB,但是TCB中所保存的线程状态比PCB表中少多了。
5、进程是系统所有资源分配时候的一个基本单位,拥有一个完整的虚拟空间地址,并不依赖线程而独立存在。
进程与程序的区别:
程序是一组指令的集合,它是静态的实体,没有执行的含义。而进程是一个动态的实体,有自己的生命周期。一般说来,一个进程肯定与一个程序相对应,并且只有一个,但是一个程序可以有多个进程,
总结:
线程是进程的一部分,进程是程序的一部分。