我试图测试一个非常简单的程序,通过OpenMP 4.0指令使用gcc 5卸载功能 . 我的目标是编写一个两个独立的任务程序,其中一个任务在加速器(即Intel MIC仿真器)上执行,另一个任务在CPU上同时执行 .
这是代码:
#include <omp.h>
#include <stdio.h>
#define limit 100000
int main(int argc, char** argv)
{
int cpu_prime, acc_prime;
#pragma omp task shared(acc_prime)
{
#pragma omp target map(tofrom: acc_prime)
{
printf("mjf-dbg >> acc computation\n");
int i, j;
acc_prime=0;
for(i=0; i<limit; i++){
for(j=2; j<=i; j++){
if(i%j==0)
break;
}
if(j==i)
acc_prime = i;
}
printf("mjf-dbg << acc computation\n");
}
}
#pragma omp task shared(cpu_prime)
{
int i, j;
cpu_prime=0;
printf("mjf-dbg >> cpu computation\n");
for(i=0; i<limit; i++){
for(j=2; j<=i; j++){
if(i%j==0)
break;
}
if(j==i)
cpu_prime = i;
}
printf("mjf-dbg << cpu computation\n");
}
#pragma omp taskwait
printf("cpu prime: %d \n", cpu_prime);
printf("gpu prime: %d \n", acc_prime);
}
使用此代码,我期待以下执行流程:
-
主线程(MT)遇到第一个显式任务区域,绑定到该任务并开始执行 .
-
遇到目标指令,MT将目标块卸载到加速器并到达调度点
-
MT返回隐式任务区域
-
MT遇到第二个显式任务区域,绑定到该任务并开始执行 .
-
MT与卸载到加速器设备的计算并行地执行主机上的计算 .
-
MT返回隐式任务区域并到达由taskwait指令引起的调度点
-
MT返回到第一个显式任务区域,等待卸载块的结束 .
编译和运行:
gcc -fopenmp -foffload="-march=knl" overlap.c -o overlap
OFFLOAD_EMUL_RUN="sde -knl --" ./overlap
输出:
mjf-dbg >> acc computation
mjf-dbg << acc computation
mjf-dbg >> cpu computation
mjf-dbg << cpu computation
cpu prime: 99991
gpu prime: 99991
这不是我期望的输出,因为这意味着主线程在调度主机任务之前正在等待卸载计算完成 . 相反,我正在寻找这样的东西:
mjf-dbg >> acc computation
mjf-dbg >> cpu computation
mjf-dbg << cpu computation
mjf-dbg << acc computation
cpu prime: 99991
gpu prime: 99991
卸载仿真器工作正常,因为在执行期间,我可以看到_offload_target进程在程序执行目标块时将达到100%的CPU使用率 .
所以问题是:有没有人知道为什么这两个任务被序列化而不是并行执行(一个在主机进程上,另一个在_offload_target仿真过程中)?
1 回答
这里有一个比卸载更基本(也更简单)的问题 - 你的任务不在并行区域 .
OpenMP tasks have to be in a parallel region,即使它们通常嵌入
omp single
中 .所以这:
连续运行任务:
而将任务放在一个平行的区域,如下所示:
按预期工作