OpenCL编译方式技术分析
OpenCL程序的动态编译
OpenCL(OpenComputionLanguage)是一种全新的针对异构系统进行并行编程的应用程序接 口(API),有效利用系统中的所有计算资源。OpenCL采用运行时动态编译的方式来执行程序,灵活高效。
OpenCL程序的编译运行方式非常特殊,运行在加速设备上的程序是由主程序在运行过程中动态的生成,并编译 、执行的 。
- kernel对象的创建、设置、查询。host程序在运行时,通过OpenCL提供的API函数clCreateKernelgIj建具体的kernel对象,通过 c1SetKernelArg设置kernel函数的参数,通过clGetKernelInfo查询kernel函数的相关信息。
- kernel 的执行。clEnqueueNDRangeKernel函数完成数据并行执行kernel的功能,clEnqueueTask函数完成任务并行执行kernel的功能。OpenCL函数一般按照入队的顺序执 行,但是可以设置是顺序执行还是乱序执行。clCreateCommandQueue0函数的properties参数可以被用来指定执行顺序 。可以用clSetCommandQueueProperty0函数来改变命令队列 的属性。在乱序执行的情况下,为了保证kernel 的特殊执行顺序,可以使用等待一个事件 。 另外 ,等待事件命令和栏栅函数可以放到命令队列里 。等待事件命令确保在该命令之前的具有等待事件标志的命令必须完成之后,后边的命令才能开始执行 ;而 栏栅 函数能够确保之前的所有命令都执行完 ,才开始执行后边的命令。
存储器对象命令也类似 。
虽然OpenCL采用运行时动态编译的方式来执行程序在一定程度上提高了灵活性,但是代价却是耗时的增加。clCreateProgramWithBinary 函数可以指定运行方式为离线编译方式,离线编译中,kernel程序使用Opencl编译器提前编译出二进制文件,在主机程序中使用Opencl API来调用编译好的二进制文件。由于主程序中直接调用二进制执行文件,所以从主程序启动到内核运行之间的时间是很小的。
但是这样做的问题是很难实现加速设备的通用性,在提供给客户运行的程序中就必须要把所有可能的平台都包进来,还必须在主程序中分类调用,增加了主机程序的复杂性。同时可执行文件也大了很多。
例子:
HelloWorld
HelloBinaryWorld
在线编译方式:time = 0.119513 s
离线编译方式:time = 0.051588 s
我们可以清楚的看到,同一套代码在不同的编译方式下,效率是有明显区别的。
具体的优略已经在上面讲的很清楚了。