我正在尝试测试一个非常简单的程序,该程序通过 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 仿真进程上)?