在offload代码中调用native代码

英特尔编译器为至强融核™ 协处理器提供的offload编译模式使得已有传统程序向该架构的移植工作变得十分灵活方便。程序员可以通过在一个可运行的主机代码中加入编译指示或者某些新的关键字使指定代码段运行在协处理器上。该模式下生成的程序既可以运行在配备

了协处理器的系统上充分利用该处理器的强大计算能力,也可以在没有协处理器的传统系统上正确地运行。

默认情况下,对于源程序中的offload代码段编译器会同时为两种目标架构生成代码。此时在offload代码段中如果调用了外部函数,那么这些外部函数也必须具有offload的属性,只有这样才能保证生成的程序可以在协处理器上调用这些函数。但是在某些特定的应用场景

下,用户可能无法保证所调用的外部函数代码也具有offload属性,比如这些函数代码只有主机CPU和协处理器的native版本,或者同一函数在主机CPU和协处理器上具有不同的源代码实现。针对这种情况,英特尔编译器支持在生成offload程序时通过特定选项为主机代码

和协处理器代码链接不同的native函数库。这样得到的程序在运行时可以根据运行环境自动调用相应的native函数库。

考虑下面的例子:

库函数原型: "foo.h"

void foo(void);

主机CPU版本: "foo_cpu.c"

#include <stdio.h>
#include "foo.h"

void foo(void)
{
 printf("Hello from CPU.\n");
}

协处理器版本: "foo_mic.c"

#include <stdio.h>
#include "foo.h"

void foo(void)
{
 printf("Hello from MIC.\n");
}

主程序 "main.c":

#pragma offload_attribute(push,target(mic))   /* Push 和 Pop之间的 */
#include "foo.h"                              /* 函数&全局变量声明可以 */
#pragma offload_attribute(pop)                /* 在offload代码段中使用 */

void main(void)
{
#pragma offload target (mic) optional
  foo();
}


生成主机CPU版本的动态链接库:"libfoocpu.so"

$icc -o libfoocpu.so -shared -fPIC foo_cpu.c

生成协处理器native版本的动态链接库: "libfoomic.so"

$icc -o libfoomic.so -shared -fPIC -mmic foo_mic.c

这里"-mmic"使编译器生成native版本的协处理器代码。


生成主程序:"main.out"

$icc -o main.out main.c -L. -lfoocpu -offload-option,mic,ld,"-L. -lfoomic"

这里的"-offload-option"被用来为协处理器代码指定特定的编译,链接选项。该例子中我们为协处理器指定了链接协处理器版本的native版本的动态链接库"libfoomic.so"。

在执行最终的可执行程序时我们还需要为主机CPU和协处理器代码指定对应的动态链接库搜索路径(这里假定可执行程序和动态链接库在同一目录下):

主机CPU代码动态链接库搜索路径

$LD_LIBRARY_PATH=$PWD:$LD_LIBRARY_PATH

协处理器native代码动态链接库搜索路径
$MIC_LD_LIBRARY_PATH=$PWD:$MIC_LD_LIBRARY_PATH


在安装了协处理器的系统上执行:
$./main.out
Hello from MIC.

在没有安装协处理器的系统上执行(上面指定协处理器native代码搜索路径的步骤可以省去):
$./main.out
Hello from CPU.

更多关于如何使用英特尔编译器开发至强融核协处理器程序的信息请参见英特尔编译器用户参考手册的相关内容。

Para obter mais informações sobre otimizações de compiladores, consulte Aviso sobre otimizações.