OpenMP: Какие примеры могут повысить производительность? - PullRequest
0 голосов
/ 24 июля 2011

Какой из них может улучшить производительность?

Пример 1

 #pragma omp parallel for private (i,j)
    for(i = 0; i < 100; i++) {
        for (j=0; j< 100; j++){
           ....do sth...
        }
    }

Пример 2

   for(i = 0; i < 100; i++) {
        #pragma omp parallel for private (i,j)
        for (j=0; j< 100; j++){
           ....do sth...
        }
    }

Контрольный вопрос Допустимо ли использовать Пример 3?

 #pragma omp parallel for private (i)
   for(i = 0; i < 100; i++) {
        #pragma omp parallel for private (j)
        for (j=0; j< 100; j++){
           ....do sth...
        }
    }

Ответы [ 2 ]

2 голосов
/ 24 июля 2011

В общем, пример 1 является лучшим, поскольку он распараллеливает самый внешний цикл, что сводит к минимуму накладные расходы на ветку / соединение потока.Хотя многие реализации OpenMP предварительно выделяют пул потоков, все еще существуют накладные расходы на отправку логических задач рабочим потокам (так называемая команда потоков) и их присоединение.Также обратите внимание, что когда вы используете динамическое планирование (например, schedule(dynamic, 1)), тогда это накладные расходы на диспетчеризацию задачи будут проблематичными.

Так, пример 2 может повлечь за собой значительные параллельные издержки, особенно когда счетчик поездок for-i большой (хотя 100 - это нормально), а объем рабочей нагрузки for-j небольшой. Маленький может быть неоднозначным термином и зависит от многих переменных.Но менее 1 миллисекунды было бы определенно расточительно для использования OpenMP.

Однако, в случае, когда for-i не распараллеливается и только for-j распараллеливается, тогда Example2 является единственным вариантом.В этом случае вы должны тщательно продумать, может ли величина параллельной рабочей нагрузки компенсировать параллельные накладные расходы.

Example3 полностью допустим, если for-i и for-j безопасно распараллеливаемы (т. Е. Нет потоковых зависимостей, переносимых циклом)в каждые две петли соответственно).Пример 3 называется вложенный параллелизм .Вы можете посмотреть эту статью .Вложенный параллелизм следует использовать с осторожностью.Во многих реализациях OpenMP вам нужно вручную включить вложенный параллелизм, вызвав omp_set_nested.Однако, поскольку вложенный параллелизм может порождать огромное количество потоков, его преимущество может быть значительно уменьшено.

1 голос
/ 24 июля 2011

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

Кстати, единственное место, где вам нужно пометить переменную как private, это "j" в примере 1. Во всех остальных случаях это неявно.

...