将英特尔的#pragma offload翻译为OpenMP for Xeon Phi(性能问题和其他问题)

时间:2016-12-26 15:49:50

标签: xeon-phi icc intel-mic offloading

我使用英特尔C ++编译器17.0.01,我有两个代码块。

第一个代码块在Xeon Phi上分配内存,如下所示:

#pragma offload target(mic:1) nocopy(data[0:size]: alloc_if(1) free_if(0))

第二个块评估上述内存并将其复制回主机:

#pragma offload target(mic:1) out(data[0:size]: alloc_if(0) free_if(0))

这段代码运行得很好,但#pragma offload只是英特尔编译器的一部分(我认为)。所以,我想将其转换为OpenMP。

这就是我将第一个块转换为OpenMP的方式:

#pragma omp target device(1) map(alloc:data[0:size])

这就是我将第二个块转换为OpenMP的方式:

#pragma omp target device(1) map(from:data[0:size])

此外,我使用了export OFFLOAD_REPORT=2以便更好地了解运行时期间发生的事情。

以下是我的问题/问题:

  • 第一个代码块的OpenMP版本与英特尔版本(#pragma offload)一样快。这里没什么奇怪的。
  • 第二个代码块的OpenMP版本比英特尔版本慢5倍。但是,两者中的MIC_TIME是相同的,但CPU_TIME是不同的(OpenMP版本更高)。那是为什么?
  • 我的英特尔指令是否最佳?
  • 是我的英特尔 - > OpenMP翻译是否正确且最优?

这里有一些其他的,有点不同的问题:

  • 在测试机器上,我有两张Intel Phi卡。由于我想使用第二个,我这样做:#pragma omp target device(1)...。这是对的吗?
  • 如果我#pragma omp target device(5)...代码仍然有效!它运行在其中一个Phi卡(而不是CPU)上,因为性能相似。那是为什么?
  • 我还在没有Xeon Phi的机器上尝试了我的软件(OpenMP版本),它在CPU上运行得很好!这有保证吗?当机器上没有加速器时,忽略target device(1)
  • 是否可以在OpenMP卸载区域内执行std::cout << print_phi_card_name_or_uid();之类的操作(因此我肯定知道我的软件正在运行哪个卡)?

1 个答案:

答案 0 :(得分:0)

第二个OpenMP代码块再次分配内存。您应该将数据映射到#pragma omp target data map(from:data[0:size]),或者只在第一个块之前添加#pragma omp target enter data map(alloc:data[0:size]),从而将数据映射到设备数据环境。

  

在测试机上我有两张Intel Phi卡。由于我想使用第二个,我这样做:#pragma omp target device(1)....这是正确的吗?

AFAIK,设备(0)表示默认卡,设备(1)表示第一张卡,设备(2)表示第二张卡。

  

如果我执行#pragma omp target device(5)...代码仍然有效!它运行在其中一个Phi卡(而不是CPU)上,因为性能相似。那是为什么?

因为liboffload does this(liboffload是gcc和icc使用的运行时库)。但是,OpenMP标准并不能保证这种行为。

  

我还在没有Xeon Phi的机器上尝试了我的软件(OpenMP版本),它在CPU上运行得很好!这有保证吗?如果机器上没有加速器,则忽略目标设备(1)?

是。不确定标准,但icc和gcc中的卸载是以这种方式实现的。

  

是否可以执行类似std :: cout&lt;&lt;的操作print_phi_card_name_or_uid();在OpenMP卸载区域内(所以我肯定知道我的软件在哪个卡上运行)?

OpenMP 4.5仅提供omp_is_initial_device()功能来区分主机和加速器。也许有一些特定于英特尔的界面可以做到这一点。