我使用英特尔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
以便更好地了解运行时期间发生的事情。
以下是我的问题/问题:
#pragma offload
)一样快。这里没什么奇怪的。MIC_TIME
是相同的,但CPU_TIME
是不同的(OpenMP版本更高)。那是为什么?这里有一些其他的,有点不同的问题:
#pragma omp target device(1)...
。这是对的吗?#pragma omp target device(5)...
代码仍然有效!它运行在其中一个Phi卡(而不是CPU)上,因为性能相似。那是为什么?target device(1)
?std::cout << print_phi_card_name_or_uid();
之类的操作(因此我肯定知道我的软件正在运行哪个卡)?答案 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()
功能来区分主机和加速器。也许有一些特定于英特尔的界面可以做到这一点。