我正在尝试测试一个非常简单的程序,该程序通过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);
}
使用此代码,我期待以下执行流程:
编译&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仿真过程中)?
答案 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