Планирование Openmp

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

  1. Параллельно запускайте первую, если в ней 16 и более шагов.
  2. В противном случае запустите второй параллельно (но не первый, даже если он имеет 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, и я не уверен, что компилятор целевого оборудования будет поддерживать это.

Любые идеи?


person Emilien    schedule 23.05.2013    source источник


Ответы (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.

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