4

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

}

使用此代码,我期待以下执行流程:

  1. 主线程 (MT) 遇到第一个显式任务区域,绑定到该任务并开始执行。
  2. 遇到目标指令,MT 将目标块卸载到加速器并到达调度点
  3. MT 回到隐式任务区域
  4. MT 遇到第二个显式任务区域,绑定到该任务并开始执行。
  5. MT 在主机上执行计算,同时将计算卸载到加速器设备。
  6. MT 回到隐式任务区域并到达由 taskwait 指令引起的调度点
  7. 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 仿真进程上)?

4

1 回答 1

1

这里有一个比卸载更基本(和更简单)的问题 - 您的任务不在并行区域中。

OpenMP 任务必须位于并行区域中,即使它们通常随后嵌入到omp single.

所以这:

#include <stdio.h>
#include <unistd.h>

int main(int argc, char** argv)
{

#pragma omp task 
    {
        printf("task 1 starts\n");
        sleep(3);
        printf("task 1 ends\n");
    }

#pragma omp task 
    {
        printf("task 2 starts\n");
        sleep(1);
        printf("task 2 ends\n");
    }

    return 0;
}

串行运行任务:

$ gcc -fopenmp brokentasks.c -o brokentasks
$ export OMP_NUM_THREADS=2

$ ./brokentasks 
task 1 starts
task 1 ends
task 2 starts
task 2 ends

而将任务放在并行区域中,如下所示:

#include <stdio.h>
#include <unistd.h>

int main(int argc, char** argv)
{

#pragma omp parallel
#pragma omp single
    {
#pragma omp task 
        {
            printf("task 1 starts\n");
            sleep(3);
            printf("task 1 ends\n");
        }

#pragma omp task 
        {
            printf("task 2 starts\n");
            sleep(1);
            printf("task 2 ends\n");
        }
    }

}

按预期工作

$ gcc -fopenmp tasks.c -o tasks
jdursi@odw-jdursi:~/tmp$ ./tasks
task 2 starts
task 1 starts
task 2 ends
task 1 ends
于 2015-08-19T20:32:54.077 回答