Opencl 如何收集二进制内核以分发专有代码

Opencl 如何收集二进制内核以分发专有代码,opencl,Opencl,我有一个包含我不想在源代码中发布的专有技术的代码。解决方案之一是提供一组预编译内核,并根据用户的硬件选择正确的二进制文件 如何用最少的二进制文件和运行离线编译器的最少机器覆盖大多数用户(AMD和Intel,因为Nvidia可以使用CUDA代码)?是否有GPU系列可以使用相同的二进制文件?CUDA编译器可以编译不同的架构,那么OpenCL呢?二进制兼容性数据似乎没有很好的文档记录,但可能有人自己收集了这些数据 我知道有SPIR,但旧的硬件不支持它 如果有人发现了这个问题并且做得比我少,下面是我的实

我有一个包含我不想在源代码中发布的专有技术的代码。解决方案之一是提供一组预编译内核,并根据用户的硬件选择正确的二进制文件

如何用最少的二进制文件和运行离线编译器的最少机器覆盖大多数用户(AMD和Intel,因为Nvidia可以使用CUDA代码)?是否有GPU系列可以使用相同的二进制文件?CUDA编译器可以编译不同的架构,那么OpenCL呢?二进制兼容性数据似乎没有很好的文档记录,但可能有人自己收集了这些数据

我知道有SPIR,但旧的硬件不支持它

如果有人发现了这个问题并且做得比我少,下面是我的实现细节。我制作了一个将内核编译成文件的工具,然后我将所有这些二进制文件收集到一个C数组中,以包含在主应用程序中:


常量字符*二进制文件[]={
//内核/HD图形4000
“\x62\x70\x6c\x69\x73\x74\x30\x30\xd4\x01\x02\x03”
“\x04\x05\x06\x07\x08\x5f\x10\x0f\x63\x6c\x42\x69”
“\x6e\x61\x72\x79\x56\x65\x72\x73\x69\x6f\x6e\x5c”
...
“\x00\x00\x00\x00\x00\x00\x00\x00\x09\x00\x00\x00\x00\x00”
“\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x47\xe0”
,
//这里有更多的谷物
};
大小\u t二进制文件\u大小[]={
204998,
205907,
...
};

然后我使用下面的代码迭代所有内核(我没有发明任何比尝试和错误更聪明的方法,选择第一个成功构建的内核,可能有更好的解决方案):


int e3=-1;
int i=0;
而(e3!=CL_成功){
if(i==lenof(二进制文件)){
抛出错误();
}
program=clCreateProgramWithBinary(上下文,1,&DeviceID[DeviceDX],&binaries\U大小[i],
(常量无符号字符**)和二进制文件[i],
nullptr和e3);
如果(e3!=CL_成功){
++一,;
继续;
}
int e4=clBuildProgram(程序,1和设备ID[devIdx],
“”,nullptr,nullptr);
e3=e4;
++一,;
}

不幸的是,您的问题没有标准的解决方案。OpenCL是独立于平台的,并且没有标准的方法(除了SPIR)来处理这个问题。每个供应商在内部决定一个不同的编译器工具链,甚至在同一个驱动程序的多个版本中,或者在不同的设备中,这一点也可能发生变化

您可以向内核添加一些元数据,以确定编译它的平台,这将节省您的试错部分(即,不只是存储二进制文件和二进制文件大小,您还可以存储二进制文件和二进制文件平台和二进制文件设备,然后遍历这些数组以查看应该加载哪个二进制文件)

对您来说,最好的解决方案是SPIR(或新的SPIRV),它是一种中间表示形式,可以由OpenCL驱动程序“重新编译”到实际的体系结构指令集。 如果您将二进制文件存储在SPIRV中,并且可以访问/了解某些编译器魔法,那么您可以使用翻译工具返回LLVM-IR,然后使用LLVM基础设施向下编译到其他平台,如AMD或PTX(请参阅)