Opencl 在线和离线编译

翻译 2016年11月24日 16:09:48

OpenCL支持在线编译和离线编译两种编译方式,主要区别是内核程序提供给主机调用方式。

mark

  • 在线编译:在host程序中引用的是Kernel的源代码建立Opencl程序
  • 离线编译:Host程序中直接能在目标器件上运行的二进制文件来简历opencl程序

离线编译中,kernel程序使用Opencl编译器提前编译出二进制文件,在主机程序中使用Opencl API来调用编译好的二进制文件。由于主程序中直接调用二进制执行文件,所以从主程序启动到内核运行之间的时间是很小的。但是这样做的问题是很难实现加速设备的通用性,在提供给客户运行的程序中就必须要把所有可能的平台都包进来,还必须在主程序中分类调用,增加了主机程序的复杂性。同时可执行文件也大了很多。

在线编译中,内核是在运行环境中(runtime)通过Opencl API库编译内核源代码。有点类似于Just in time 编译–JIT编译解释。这种方法的优点就是可以不依赖于具体设备类型的就可以发布主机端程序,程序会在运行的时候自动去适配具体的设备。同时避免每次都去编译内核,减少了开发测试的负担。但是这种方式不适合需要达到实时效果的嵌入式系统。同时由于可以从主机程序中读取到内核程序,并不适于商业应用。

Opencl运行库包含了一组能完全实现上面操作的API。某种程度上来说,由于Opencl是一个异构环境的编程框架,支持在线编译并不是个稀奇的事情。事实上,NVIDIA,AMD和APPLE的OPENCL环境并没有一个完全独立的OPENCL编译器。因此,如果需要在这些环境中得到一个内核二进制文件,还需要主机程序在执行的时候把编译出来的执行文件写进一个文档。

比较在线编译和离线编译示例:

在线编译
先从文件中读取内核原代码

const char fileName[] = "./kernel.cl";
...
fp = fopen(fileName, "r");
if (!fp) {
    fprintf(stderr, "Failed to load kernel.\n");
    exit(1);
}
source_str = (char *)malloc(MAX_SOURCE_SIZE);
source_size = fread(source_str, 1, MAX_SOURCE_SIZE, fp);
fclose(fp);

然后在主程序中使用clCreateProgramWithSource使用源代码创建程序,并使用clBuildProgram实现在线编译

/* Create Kernel program from the read in source */
    program = clCreateProgramWithSource(context, 1, (const char **)&source_str, (const size_t *)&source_size, &ret);

/* Build Kernel Program */
    ret = clBuildProgram(program, 1, &device_id, NULL, NULL, NULL);

离线编译
先读取内核程序的二进制文件

char fileName[] = "./kernel.clbin";
...
fp = fopen(fileName, "r");
if (!fp) {
    fprintf(stderr, "Failed to load kernel.\n");
    exit(1);
}
binary_buf = (char *)malloc(MAX_BINARY_SIZE);
binary_size = fread(binary_buf, 1, MAX_BINARY_SIZE, fp);
fclose(fp);

然后使用clCreateProgramWithBinary使用二进制创建程序

/* Create kernel program from the kernel binary */
    program = clCreateProgramWithBinary(context, 1, &device_id, (const size_t *)&binary_size,(const unsigned char **)&binary_buf, &binary_status, &ret);

对比可以发现不需要使用clBuildProgram()编译

原文中作者安装了foxc编译器,这个编译器有独立的内核编译器,可以让读者可以更清楚的了解在线编译和离线编译的过程。
作者使用了foxc -o kernel.clbin kernel.cl编译出独立的内核二进制文件

原文:opencl在线和离线编译

OpenCL编译环境配置(VS+Nvidia)

英伟达的显卡首先要下载安装CUDA开发包,可以参考这里的步骤:   VS2015编译环境下CUDA安装配置 安装好CUDA之后,OpenCL的配置就已经完成了80%了,剩下的工作就是把OpenCL的路...
  • dcrmg
  • dcrmg
  • 2017-02-16 07:17:27
  • 3061

【VS2013】OpenCl环境搭建&helloworld

前面几步都比较简单,最后一步需要如下3小步: 1.项目属性->VC++目录->包含目录(include),C:\Program Files (x86)\AMD APP SDK\2.9\include。...
  • hermittt
  • hermittt
  • 2016-02-15 15:56:42
  • 5291

opencl:慎用-cl-opt-disable选项编译kernel(可能会导致一些无法解释的问题)

在编译opencl kernel代码时,有一个编译选项-cl-opt-disable。根据opencl 官网的原文描述,使用这个选项可以关闭所有的代码优化,便于调试程序。(默认情况下,编译优化选项是打...
  • 10km
  • 10km
  • 2016-04-21 15:00:01
  • 1364

OpenCL编程步骤(三):创建和编译程序

OpenCL程序是由一组内核组成,而这些内核就是程序源码中以限定符__kernel声明的函数。__kernel函数可能会用到一些辅助函数以及常量数据,他们也是程序的一部分。 1、创建...
  • u013684730
  • u013684730
  • 2015-05-27 16:26:58
  • 1332

OpenCL学习笔记(三):OpenCL安装,编程简介与helloworld

从图中可以看出(参考《OpenCL 编程入门》): 1. 异构计算设备,可以是CPU或GPU。现在也有支持OpenCL的FPGA设备和至强融核协处理设备(MIC)。 2. OpenCL的API通过Co...
  • xbinworld
  • xbinworld
  • 2015-06-14 23:37:27
  • 8216

从零开始做OpenCL开发》系列文章的第一篇。

本文将作为我《从零开始做OpenCL开发》系列文章的第一篇。   1 异构计算、GPGPU与OpenCL   OpenCL是当前一个通用的由很多公司和组织共同发起的多CPU\GPU\...
  • Tommy_wxie
  • Tommy_wxie
  • 2016-08-04 22:44:38
  • 1815

opencl:改造C++接口增加对内存编译(compile)的支持

OpenCL 1.2以前的标准(1.0,1.1),只支持单个源文件编译成可执行程序(Executable Program),所以只提供了clBuildProgram函数。 从OpenCL 1.2以后...
  • 10km
  • 10km
  • 2016-03-03 16:38:39
  • 1167

MAC OSX 多文件编译链接

现在有两个文件:main.c和source.cmain.c作为驱动程序,用来测试源代码;source.c为源代码main.c#include int c_entry(void);int main(in...
  • abcamus
  • abcamus
  • 2016-11-22 17:09:28
  • 44548

静态集成 OpenCL 的 Kernel 源代码到可执行文件

在编写OpenCL代码时,为了方便起见,我们更喜欢将kernel源代码放在单独的文件中(一般为*.cl)。这各做的缺点在于,程序需要在运行时动态读入文件中的代码为字符串,然后再传递给OpenCL的RT...
  • JackyTintin
  • JackyTintin
  • 2015-06-23 14:26:38
  • 2066

clang 分析OpenCL 代码

目前仅实现了对参数qualifier的提取,可以很方便在ast上加入其他操作。 #include #include "llvm/Support/Host.h" #include "llvm/ADT/...
  • zhangxx0811
  • zhangxx0811
  • 2014-02-26 03:44:06
  • 1909
收藏助手
不良信息举报
您举报文章:Opencl 在线和离线编译
举报原因:
原因补充:

(最多只允许输入30个字)