OpenMP 4.0 - GCC 5.2.0 - 重叠设备和主机任务执行

时间:2015-08-19 10:39:50

标签: c multithreading openmp hardware-acceleration xeon-phi

我正在尝试测试一个非常简单的程序,该程序通过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. 引起的调度点
  8. MT返回第一个显式任务区域,等待卸载块的结束。
  9. 编译&amp;运行:

    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 个答案:

答案 0 :(得分:1)

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

OpenMP tasks have to be in a parallel region,即使它们通常嵌入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