Использование openmp лучше - PullRequest
       6

Использование openmp лучше

2 голосов
/ 19 февраля 2012

Я пытаюсь реализовать openMP, но, как и многие другие плакаты до меня, результатом было просто замедлить код. Вдохновленный предыдущими ответами, я перешел от использования #pragma omp parallel for к #pragma omp task в надежде, что смогу избежать некоторых накладных расходов. К сожалению, распараллеленный код все еще в два раза медленнее, чем последовательный. Из других ответов кажется, что правильная процедура зависит от конкретных требований кода, поэтому я подумал, что мне придется самому задать вопрос.

Сначала псевдокод:

#pragma omp parallel
{
#pragma omp master
while (will be run some hundreds of millions of times)
{
    for (between 5 and 20 iterations)
    {
        #pragma omp task
        (something)
    }
    #pragma omp taskwait <- it is important that all the above tasks are completed before going on

    (something)

    if (something)
    {
        (something)

        for (between 50 and 200 iterations)
        {
            #pragma omp task 
            (something)
        }
        #pragma omp taskwait

        (something)
    }

}
}

Только два цикла for могут быть распараллелены, остальные должны быть выполнены в правильном порядке. Я придумал поместить параллельные и главные директивы вне цикла while, чтобы уменьшить накладные расходы на создание команды.

Мне также немного любопытно, правильно ли я использую taskwait - в спецификации говорится, что «родительская задача» приостановлена ​​до тех пор, пока не будут выполнены все дочерние задачи, но не совсем ясно, применима ли здесь и эта терминология, где области задач не являются вложенными.

Может кто-нибудь придумать лучший способ использования openMP, чтобы я мог получить ускорение?

РЕДАКТИРОВАТЬ: каждый шаг в цикле while зависит от всех предыдущих шагов, и поэтому они должны выполняться последовательно, с обновлением в конце. Это реализация "алгоритма, управляемого событиями" для моделирования нейронных сетей, если кому-то интересно.

Ответы [ 3 ]

2 голосов
/ 19 февраля 2012

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

Изменение кода с #pragma omp parallel for на #pragma omp task не принесет вам существенных улучшений, поскольку их разница во времени выполненияобычно пренебрежимоПрежде чем пытаться настроить некоторые рутинные вызовы или вычисления omp, вам нужно адаптировать вашу проблему к параллельному выполнению.Вам действительно нужно думать «параллельно», чтобы получить хорошее и масштабируемое увеличение производительности, просто адаптация последовательного кода работает редко.

В вашем коде вы должны попытаться парализовать цикл while, а не внутренний цикл for.Если вы парализуете малый цикл for, вы не получите значительного увеличения производительности.

0 голосов
/ 20 февраля 2012

вы не забыли установить соответствующие переменные окружения? OMP_NUM_THREADS = N, где N - количество потоков или ядер, поддерживаемых вашим процессором

0 голосов
/ 19 февраля 2012

Я не уверен, что задание - правильный путь. Я не знаком с задачами, но кажется, что он запускает поток каждый раз, когда вы сталкиваетесь с #pragma omp task. Я предпочел бы попробовать что-то вроде:

while (will be run some hundreds of millions of time)
{
#pragma omp parallel
{
    for (between 5 and 20 iterations)
    {
        (something) 
    }
#pragma omp single/master
{

    (something)
    bool flag = false;
    if (something)
    {
        (something)
        flag = true;
    }
}

    if (flag)
    {
        for (between 50 and 200 iterations)
        {
            (something)
        }
    }
#pragma omp single/master
{
            (something)
}
    }
    }

Также важно помнить, что задачи в циклах for могут быть слишком маленькими для параллельного выполнения, чтобы дать какое-либо ускорение, так как есть издержки при запуске и синхронизации потоков. Вам также следует рассмотреть возможность переписывания вашей программы, чтобы вам не нужно было синхронизировать потоки, что вы сейчас делаете довольно много. Я предполагаю, что ваш алгоритм и рабочая нагрузка на самом деле слишком малы для параллельного выполнения, чтобы дать какое-либо ускорение, как написано прямо сейчас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...