CUDA3.0编程接口.docx

上传人:自*** 文档编号:126223722 上传时间:2020-03-23 格式:DOCX 页数:24 大小:81.40KB
返回 下载 相关 举报
CUDA3.0编程接口.docx_第1页
第1页 / 共24页
CUDA3.0编程接口.docx_第2页
第2页 / 共24页
CUDA3.0编程接口.docx_第3页
第3页 / 共24页
CUDA3.0编程接口.docx_第4页
第4页 / 共24页
CUDA3.0编程接口.docx_第5页
第5页 / 共24页
点击查看更多>>
资源描述

《CUDA3.0编程接口.docx》由会员分享,可在线阅读,更多相关《CUDA3.0编程接口.docx(24页珍藏版)》请在金锄头文库上搜索。

1、CUDA 3.0 编程接口目前可用两种接口写CUDA程序:CUDA C和CUDA驱动API。一个应用典型的只能使用其中一种,但是遵守3.4节描述的限制时,可以同时使用两种。CUDA C将CUDA编程模型作为C的最小扩展集展示出来。任何包含某些扩展的源文件必须使用nvcc 编译,nvcc的概要在3.1节。这些扩展允许程序员像定义C函数一样定义内核和在每次内核调用时,使用新的语法指定网格和块的尺寸。CUDA驱动API是一个低层次的C接口,它提供了从汇编代码或CUDA二进制模块中装载内核,检查内核参数,和发射内核的函数。二进制和汇编代码通常可以通过编译使用C写的内核得到。CUDA C包含运行时API

2、,运行时API和驱动API都提供了分配和释放设备存储器、在主机和内存间传输数据、管理多设备的系统的函数等等。运行时API是基于驱动API的,初始化、上下文和模块管理都是隐式的,而且代码更简明。CUDA C也支持设备模拟,这有利于调试(参见节3.2.8)。相反,CUDA驱动API要求写更多的代码,难于编程和调试,但是易于控制且是语言无关的,因为它处理的是二进制或汇编代码。3.2节接着第二章介绍CUDA C。也引入了CUDA C和驱动API共有的概念:线性存储器、CUDA数组、共享存储器、纹理存储器、分页锁定主机存储器、设备模拟、异步执行和与图形学API互操作。3.3节会介绍有关这些概念的知识和描

3、述它们在驱动API中是怎样表示的。3.1 用nvcc编译内核可以使用PTX编写,PTX就是CUDA指令集架构,PTX参考手册中描述了PTX。通常PTX效率高于像C一样的高级语言。无论是使用PTX还是高级语言,内核都必须使用nvcc编译成二进制代码才能在设备在执行。nvcc是一个编译器驱动,简化了C或PTX的编译流程:它提供了简单熟悉的命令行选项,同时通过调用一系列实现了不同编译步骤的工具集来执行它们。本节简介了nvcc的编译流程和命令选项。完整的描述可在nvcc用户手册中找到。3.1.1 编译流程nvcc可编译同时包含主机代码(有主机上执行的代码)和设备代码(在设备上执行的代码)的源文件。nv

4、cc的基本流程包括分离主机和设备代码并将设备代码编译成汇编形式(PTX)或/和二进制形式(cubin对象)。生成的主机代码要么被输出为C代码供其它工具编译,要么在编译的最后阶段被nvcc调用主机编译器输出为目标代码。应用能够:1.要么在设备上使用CUDA驱动API装载和执行PTX源码或cubin对象(参见3.3节)同时忽略生成的主机代码(如果有);2.要么链接到生成的主机代码;生成的主机代码将PTX代码和/或cubin对象作为已初始化的全局数据数组导入,还将2.1节引入的语法转化为必要的函数调用以加载和发射每个已编译的内核。应用在运行时装载的任何PTX代码被设备驱动进一步编译成二进制代码。这称

5、为即时编译。即时编译增加了应用装载时间,但是可以享受编译器的最新改进带来的好处。也是当前应用能够在未来的设备上运行的唯一方式,细节参见3.1.4节。3.1.2 二进制兼容性二进制代码是由架构确定的。生成cubin对象时,使用编译器选项-code指定目标架构:例如,用-code=sm_13编译时,为计算能力1.3的设备生成二进制代码 。二进制兼容性保证向后兼容,但不保证向前兼容,也不保证跨越主修订号兼容。换句话说,为计算能力为X.y生成的cubin对象只能保证在计算能力为X.z的设备上执行,这里,z=y。3.1.3 PTX兼容性一些PTX指令只被高计算能力的设备支持。例如,全局存储器上的原子指令

6、只在计算能力1.1及以上的设备上支持;双精度指令只在1.3及以上的设备上支持。将C编译成PTX代码时,-arch编译器选项指定假定的计算能力。因此包含双精度计算的代码,必须使用“-arch=sm_13”(或更高计算能力)编译,否则双精度计算将被降级为单精度计算。为某些特殊计算能力生成的PTX代码始终能够被编译成相等或更高计算能力设备上的二进制代码。3.1.4 应用兼容性为了在特定计算能力的设备上执行代码,应用加载的二进制或PTX代码必须满足如3.1.2节和3.1.3节说明的计算能力兼容性。特别地,为了能在将来更高计算能力(不能产生二进制代码)的架构上执行,应用必须装载PTX代码并为那些设备即时

7、编译。CUDA C应用中嵌入的PTX和二进制代码,由-arch和-code编译器选项或-gencode编译器选项控制,详见nvcc用户手册。例如nvcc x.cugencode arch=compute_10,code=sm_10gencode arch=compute_11,code=compute_11,sm_11嵌入与计算能力1.0兼容的二进制代码(第一个-gencode选项)和PTX和与计算能力1.1兼容的二进制代码(第二个-gencode选项)。生成的主机代码在运行时自动选择最合适的代码装载并执行,对于上面例子,将会是:1.0二进制代码为计算能力1.0设备,1.1二进制代码为计算能力

8、1.1,1.2,1.3的设备,通过为计算能力2.0或更高的设备编译1.1PTX代码获得的二进制代码。例如,x.cu可有一个使用原子指令的优化代码途径,只能支持计算能力1.1或更高的设备。_CUDA_ARCH_宏可以基于计算能力用于不同的代码途径。它只为设备代码定义。例如,当使用“arch=compte_11”编译时,_CUDA_ARCH_等于110。使用驱动API的应用必须将代码编译成分立的文件,且在运行时显式装载和执行最合适的文件。nvcc用户手册为-arch,-code和-gencode编译器选项列出了多种简写。如“arch=sm_13”是“arch=compute_13 ?code=co

9、mpute_13,sm_13”的简写(等价于“-gencode arch=compute_13,code=compute_13,sm_13”)。3.2 CUDA CCUDA C为熟悉C语言的用户提供了一个简单途径,让他们能够轻易的写出能够在设备上执行的程序。CUDA C包含了一个C语言的最小扩展集和一个运行时库。语言核心扩展在第二章已经介绍了。本节继续介绍运行时。所有扩展的完整的描述可在附录B找到,CUDA运行时的完整描述可在CUDA参考手册中找到。cudart动态库是运行时的实现,它所有的入口点前缀都是cuda。运行时没有显式的初始化函数;在初次调用运行时函数(更精确地,不在参考手册中设备和

10、版本管理节中的任何函数)时初始化。在计算运行时函数调用时间和解析初次调用运行时产生的错误码时必须牢记这点。一旦运行时在主机线程中初始化,在主机线程中通过一些运行时函数调用分配的任何资源(存储器,流,事件等)只在当前主机线程的上下文中有效。因此只有在这个主机线程中调用的运行时函数(存储器拷贝,内核发射等)才能操作这些资源。这是因为CUDA上下文(参见3.3.1节)作为初始化的一部分建立且成为主机线程的当前上下文,且不能成为其它主机线程的当前上下文。在多设备的系统中,内核默认在0号设备上执行,详见3.2.3节。3.2.1 设备存储器正如2.4节所提到的,CUDA编程模型假定系统包含主机和设备,它们

11、各有自己独立的存储器。内核不能操作设备存储器,所以运行时提供了分配,释放,拷贝设备存储器和在设备和主机间传输数据的函数。设备存储器可被分配为线性存储器或CUDA数组。CUDA数组是不透明的存储器层次,为纹理获取做了优化。它们的细节在3.2.4节。计算能力1.x的设备,其线性存储器存在于32位地址空间内,计算能力2.0的设备,其线性存储器存在于40位地址空间内,所以独立分配的实体能够通过指针引用,如,二叉树。典型地,线性存储器使用cudaMalloc()分配,通过cudaFree()释放,使用cudaMemcpy()在设备和主机间传输。在2.1节的向量加法代码中,向量要从主机存储器复制到设备存储

12、器:/Device code_global_voidVecAdd(float*A,float*B,float*C,intN) inti=blockDim.x*blockIdx.x+threadIdx.x;if(iN)Ci=Ai+Bi;/Host codeintmain()intN=.;size_t size=N*sizeof(float);/Allocate input vectors h_A and h_B in host memoryfloat*h_A=(float*)malloc(size);float*h_B=(float*)malloc(size);/Initialize input

13、 vectors./Allocate vectors in device memoryfloat*d_A;cudaMalloc(void*)&d_A, size);float*d_B;cudaMalloc(void*)&d_B, size);float*d_C;cudaMalloc(void*)&d_C, size);/Copy vectors from host memory to device memorycudaMemcpy(d_A, h_A, size, cudaMemcpyHostToDevice);cudaMemcpy(d_B, h_B, size, cudaMemcpyHostT

14、oDevice);/Invoke kernelintthreadsPerBlock=256;线性存储器也可以通过cudaMallocPitch()和cudaMalloc3D()分配。在分配2D或3D数组的时候,推荐使用,因为这些分配增加了合适的填充以满足5.3.2.1节的对齐要求,在按行访问时或者在二维数组和设备存储器的其它区域间复制(用cudaMemcpy2D()和cudaMemcpy3D()函数)时,保证了最佳性能。返回的步长(pitch,stride)必须用于访问数组元素。下面的代码分配了一个尺寸为width*height的二维浮点数组,同时演示了怎样在设备代码中遍历数组元素。/Host

15、 codefloat*devPtr;intpitch;cudaMallocPitch(void*)&devPtr,&pitch,width*sizeof(float), height);MyKernel(devPtr, pitch);/Device code_global_voidMyKernel(float*devPtr,intpitch) for(intr=0; rheight;+r) float*row=(float*)(char*)devPtr+r*pitch);for(intc=0; cwidth;+c) floatelement=rowc;演示/Host codecudaPitchedPtr devPit

展开阅读全文
相关资源
相关搜索

当前位置:首页 > IT计算机/网络 > 其它相关文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号