linux环境下,使用MIC架构的Xeon Phi(至强融核)协处理器进行进行host+mic编程时,源程序运行的毫无问题,但将其通过ar命令生成静态连接库供其他应用程序使用时,就会出现offload error: cannot find offload entry错误。
为了简化问题,将项目源码缩略为如下示例程序。
源文件offloadtest.cpp:
#include
#include
#include
__attribute__((target(mic)))
void test_kernel(){
int thread_num=omp_get_max_threads();//获取处理器最大可并行的线程数
#pragma omp parallel for num_threads(thread_num)
for(int i=0;i<10;++i)
printf("%d:in test kernel\n",i);
}
int main(int argc,char* argv[]){
int dev=0;
#pragma offload target(mic:dev)
{
test_kernel();
}
}
编译指令:
使用intel C++编译器icpc进行编译,编译指令如下:
icpc -openmp -o offload.out offloadtest.cpp
执行offload.out,输出结果:
0:in test kernel
7:in test kernel
4:in test kernel
8:in test kernel
2:in test kernel
6:in test kernel
9:in test kernel
3:in test kernel
1:in test kernel
5:in test kernel
可见,for循环的代码已经在MIC上被多线程并行化执行,这样我们就利用MIC达到了CPU和MIC协同编程。
利用offload将设备代码加载到MIC端执行,这种,CPU和MIC协同计算的编程模式叫加载模式(offload模式),CPU端发起主函数,通过offload模式调用kernel到MIC上之行。
在上面的代码中,将main()修改为调用MIC段代码的普通函数,修改结果如下:
#include
#include
#include
__attribute__((target(mic)))
void test_kernel(){
int thread_num=omp_get_max_threads();//获取处理器最大可并行的线程数
#pragma omp parallel for num_threads(thread_num)
for(int i=0;i<10;++i)
printf("%d:in test kernel\n",i);
}
void userKernel(){
int dev=0;
#pragma offload target(mic:dev)
{
test_kernel();
}
}
利用icpc和ar命令将修改后的代码生成静态连接库offloadtest.a。生成静态链接库库makefile指令如下:
offloadtest.a:offloadtest.o
ar crv $@ offloadtest.o
offloadtest.o:offloadtest.cpp
icpc -openmp -o offload.out offloadtest.cpp
执行makefile就会生成静态链接库offloadtest.a。当offloadtest.a链接到其他应用程序时,调用MIC设备端函数test_kernel()时就会出现运行时错误:offload error: cannot find offload entry,程序崩溃。
生成静态链接库时,使用如下指令:
offloadtest.a:offloadtest.o
xiar -qoffload-build crv $@ offloadtest.o
offloadtest.o:offloadtest.cpp
icpc -openmp -o offload.out offloadtest.cpp
在使用ar或者xiar时,加上-qoffload-build
命令选项就可以了。本人实践证明,使用xiar时不加-qoffload-build
命令选项也可以。
参考资料来自于Intel开发者社区,其原文如下:
From your question, it is unclear if your OpenMP code that worked was a host only or a host+offload code.
From what you have described, I suspect your app’s build procedure creates or uses static archives and one must contain your routine with the offload section; however, if the archive containing that routine was not built using xiar -qoffload-build then the required MIC specific archive is not created. While your app links, the MIC-image is missing the MIC-instance of the routine, so at execution time the host-side app reaches the offload, loads the MIC-image, but the run-time cannot find the routine because it does not exist.
You can visit this compiler reference on how to create offload libraires using xiar and xild.
但是需要注意的是,ar加上-qoffload-build
命令选项或者使用xiar就会生成两个静态链接库,如offloadtest.a和offloadtestMIC.a,使用时,请将这两个静态链接库一并链接到程序中使用。
xiar是Intel 基于ar封装的一个用于生成静态链接库的工具。
查看ar的命令选项:
q[f] - quick append file(s) to the archive
即,-q
后面接相关文件,ar -q
的作用就是将指定的文件快速附加到静态链接库中。
[1]https://software.intel.com/en-us/forums/intel-many-integrated-core/topic/361425
[2]http://blog.csdn.net/k346k346/article/details/50083895