11.5 C++ AMP的编译流

上一节中我们了解了C++ AMP与OpenCL的对应关系,那么对于编译和链接C++ AMP程序的方式也应该很容易理解。具体到CLamp编译器上,其进行如下的一些操作:

  1. 写完代码之后,将C++ AMP源码以“设备端模式”进行编译(所有C++ AMP指定的语言规则都会检查并应用)。CLamp编译器可以产生相应的OpenCL内核(基于AMP的约束函数),并将其编译成LLVM的位码文件。内核所调用的函数都必须是内联函数。主机端程序也会编译成生成相应的位代码,然后生成对应的C++函数。
  2. LLVM位代码通过一些变化来保证底层OpenCL程序的正确性。首先是对主机端代码的修整,然后确保在OpenCL程序中内核和指令中所使用的指针地址空间的正确性(global, constant, local, private)。这里需要注意的是,C++ AMP和OpenCL的指针在地址空间上是不相同的。OpenCL中,地址空间值指针类型的一种,而在C++ AMP中其为指针值的一种。因此,静态编译分析器会,通过指针的负值和使用操作,自行推断所使用的指针的地址空间。另外,对LLVM位数据的转换也会使用到元数据,使其能与OpenCL SPIR格式兼容。
  3. 将LLVM位码编译成OpenCL SPIR位码之后,就可以在支持cl_khr_spir扩展特性的平台上直接链接和执行。编译后的二进制文件会以另外的形式保存,其格式与主机端程序的格式是不一样的。另外,OpenCL C格式的内核代码可以使用在任何支持OpenCL平台的设备上,即使对应的设备不支持SPIR模式。
  4. 输入的C++ AMP源码会以“主机模式”对主机端代码进行编译。C++ AMP头文件都是设计好的,所以不会有内核代码在主机端模式下进行编译。不过,程序会调用C++ AMP运行时API函数来取代内核执行部分的代码。
  5. 主机端和设备端代码最终都会链接在一起,并产生一个可执行文件