Я пытаюсь протестировать очень простую программу, которая использует возможности разгрузки gcc 5 через директивы OpenMP 4.0. Моя цель — написать программу с двумя независимыми задачами, при этом одна задача выполняется на ускорителе (например, эмуляторе Intel MIC), а другая — одновременно на процессоре.
Вот код:
#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% использование ЦП, когда программа выполняет целевой блок.
Итак, вопрос: кто-нибудь знает, почему две задачи сериализуются, а не выполняются параллельно (одна в хост-процессе, а другая в процессе эмуляции _offload_target)??
-march=pentium
и запустить ее на KNC, потому что KNC требует специального значенияe_machine
в заголовке ELF (EM_K1OM
). - person Ilya Verbin   schedule 23.08.2015