2013-05-23 4 views
0

У меня есть часть кода с двумя вложенными циклами. Когда у первого есть несколько шагов, у второго есть много, а наоборот. Я могу запускать оба цикла с omp для директив самостоятельно, и у меня есть последовательные результаты (и некоторое ускорение). Однако я хотел бы:Openmp scheduling

  1. Запустить первый один параллельно, если он имеет 16 шагов или больше
  2. Else запустить второй параллельно (но не первый, даже если он имеет 8 шагов)

Это не вложенный параллелизм, потому что либо один цикл параллелен, либо другой. Если я запускаю их самостоятельно и запускаю top -H для просмотра потоков, я иногда наблюдаю только один поток, иногда больше (в каждом случае), поэтому то, что я хочу сделать, имеет смысл и фактически улучшит производительность?

До сих пор я сделал что-то вроде этого:

#pragma omp parallel 
{ 
    #pragma omp for schedule(static,16) 
    for(...){ 
     /* some declarations */ 
     #pragma omp for schedule(static,16) nowait 
     for(...){ 
      /* ... */ 
     } 
    } 
} 

, который не компилируется (работа по обмену региона не может быть тесно вложена внутри разделения труда, критические, упорядоченные, мастер или неявное область задач) и которые не будут вести себя так, как я описал. Я также попытался свернуть, но имел проблемы с «/ * некоторыми декларациями * /», и я бы хотел избежать этого, так как это openmp3.0, и я не уверен, что компилятор целевого оборудования будет поддерживать это.

Любые идеи?

ответ

1

Вы не можете встраивать конструкты совместного использования, которые привязаны к одной и той же параллельной области, но вы можете использовать вложенный параллелизм и выборочно деактивировать регионы с помощью предложения if(condition). Если condition оценивает значение true во время выполнения, то регион активен, в противном случае он выполняется последовательно. Это будет выглядеть следующим образом:

/* Make sure nested parallelism is enabled */ 
omp_set_nested(1); 

#pragma omp parallel for schedule(static) if(outer_steps>=16) 
for(...){ 
    /* some declarations */ 
    #pragma omp parallel for if(outer_steps<16) 
    for(...){ 
     /* ... */ 
    } 
} 

Недостатком здесь является то, что внутренняя область вводит небольшие накладные расходы, если она не активна во время выполнения. Если вы хотите повысить эффективность и готовы принести в жертву ремонтопригодность для этого, вы можете написать две разные реализации вложенного цикла и ветви на соответствующий, основанный на значении outer_steps.

+0

Привет и спасибо. На самом деле я закончил писать две разные параллельные области внутри if() {} else {}, как вы сказали. Это уродливо, но это довольно эффективно. Я попробую ваше решение, когда я буду искать что-то элегантное. – Emilien