【IT168 文档】目前可用两种接口写CUDA程序:CUDA C和CUDA驱动API。一个应用典型的只能使用其中一种,但是遵守3.4节描述的限制时,可以同时使用两种。
CUDA C将CUDA编程模型作为C的最小扩展集展示出来。任何包含某些扩展的源文件必须使用nvcc 编译,nvcc的概要在3.1节。这些扩展允许程序员像定义C函数一样定义内核和在每次内核调用时,使用新的语法指定网格和块的尺寸。
CUDA驱动API是一个低层次的C接口,它提供了从汇编代码或CUDA二进制模块中装载内核,检查内核参数,和发射内核的函数。二进制和汇编代码通常可以通过编译使用C写的内核得到。
CUDA C包含运行时API,运行时API和驱动API都提供了分配和释放设备存储器、在主机和内存间传输数据、管理多设备的系统的函数等等。
运行时API是基于驱动API的,初始化、上下文和模块管理都是隐式的,而且代码更简明。CUDA C也支持设备模拟,这有利于调试(参见节3.2.8)。
相反,CUDA驱动API要求写更多的代码,难于编程和调试,但是易于控制且是语言无关的,因为它处理的是二进制或汇编代码。
3.2节接着第二章介绍CUDA C。也引入了CUDA C和驱动API共有的概念:线性存储器、CUDA数组、共享存储器、纹理存储器、分页锁定主机存储器、设备模拟、异步执行和与图形学API互操作。3.3节会介绍有关这些概念的知识和描述它们在驱动API中是怎样表示的。
3.1 用nvcc编译
内核可以使用PTX编写,PTX就是CUDA指令集架构,PTX参考手册中描述了PTX。通常PTX效率高于像C一样的高级语言。无论是使用PTX还是高级语言,内核都必须使用nvcc编译成二进制代码才能在设备在执行。
nvcc是一个编译器驱动,简化了C或PTX的编译流程:它提供了简单熟悉的命令行选项,同时通过调用一系列实现了不同编译步骤的工具集来执行它们。本节简介了nvcc的编译流程和命令选项。完整的描述可在nvcc用户手册中找到。
3.1.1 编译流程
nvcc可编译同时包含主机代码(有主机上执行的代码)和设备代码(在设备上执行的代码)的源文件。nvcc的基本流程包括分离主机和设备代码并将设备代码编译成汇编形式(PTX)或/和二进制形式(cubin对象)。生成的主机代码要么被输出为C代码供其它工具编译,要么在编译的最后阶段被nvcc调用主机编译器输出为目标代码。
应用能够:
1.要么在设备上使用CUDA驱动API装载和执行PTX源码或cubin对象(参见3.3节)同时忽略生成的主机代码(如果有);
2.要么链接到生成的主机代码;生成的主机代码将PTX代码和/或cubin对象作为已初始化的全局数据数组导入,还将2.1节引入的<<<…>>>语法转化为必要的函数调用以加载和发射每个已编译的内核。
应用在运行时装载的任何PTX代码被设备驱动进一步编译成二进制代码。这称为即时编译。即时编译增加了应用装载时间,但是可以享受编译器的最新改进带来的好处。也是当前应用能够在未来的设备上运行的唯一方式,细节参见3.1.4节。