2016-12-10 9 views
0

Я новичок в OpenMP, и моя задача состоит в том, чтобы улучшить код, приведенный ниже, используя две различные возможности:OpenMP для цикла

// Size = 400, CHUNKSIZE = 100 and there are 4 threads 
#pragma omp parallel for schedule(static, CHUNK_SIZE) 
    for(int i=0; i<SIZE; i++){ 
     for(int k=0; k<i; k++){ 
      A[i][k] = 42*foo 
     } 
    } 

В первом я хотел бы изменить расписание от статического ориентироваться, потому что работа в второй цикл неуравновешен и неуклонно растет. Итак, сначала размер куска начинается с больших и уменьшается, чтобы лучше справляться с дисбалансом нагрузки между итерациями. Чем больше «становится», тем больше работы для второго цикла. На данный момент я не уверен, если динамика может быть лучше, чем руководствоваться?

Для второй возможности я понятия не имею.

+2

StackOverflow - это не сайт, который просто сбрасывает вам задачи. Вы должны показать, что вы пробовали, и сузить до определенной проблемы. Кроме того, нет смысла рассуждать о производительности пустого цикла. – Zulan

+0

Кроме того, ваш код имеет опечатки и плохой интервал. Пожалуйста, покажите еще несколько усилий в этом сообщении, прежде чем задавать вопрос ... – NoseKnowsAll

+0

Я отредактировал мой вопрос. Теперь лучше? –

ответ

1

Итак, вы знаете, посмотрев на код, в котором есть проблемы с балансировкой нагрузки, IMO вы должны протестировать с расписанием (статический, 1), чтобы гарантировать минимальную балансировку нагрузки между потоками (при максимальной только одной итерации). Чем вы сравните с графиком (dynamic, 1) и убедитесь, что накладные расходы на использование динамических (динамические с внутренним механизмом блокировки) перегружены усилением в балансировке работы между потоками.

если вы тщательно проверить, работа внутреннего контура растет как треугольник (N = SIZE):

*k/i 0 1 2 3 4 5 ... N-1 
* 0 - x x x x x ... x 
* 1 - - x x x x ... x 
* 2 - - - x x x ... x 
* 3 - - - - x x ... x 
* 4 - - - - - x ... x 
* 5 - - - - - - ... x 
* . - - - - - - ... x 
* . - - - - - - ... x 
*N-1 - - - - - - ... -  
* N - - - - - - ... - 

Таким образом, вы можете сделать свой собственный дистрибутив, чтобы гарантировать, что нить производительность итерации 0 производительность итерации N- 1, поток, который показывает производительность итерации 1 итерации N-2 и т. Д. Таким образом, вы гарантируете, что для каждого итерационного потока будут выполняться итерации внутреннего цикла N - 1.

что-то вроде этого:

int halfSIZE = SIZE >> 1; 

    #pragma omp for schedule (static,1) nowait 
    for(int i = 0; i < halfSIZE; i++) 
    { 
     for(int k=0; k<i; k++) 
      A[i][k] = 42*foo 
    } 

    #pragma omp for schedule (static,1)  
    for(int i = SIZE - 1; i >= halfSIZE; i--) 
    { 
      for(int k=0; k<i; k++) 
      A[i][k] = 42*foo 
    } 
+0

Что вы думаете об идее обрушения двух уровней циклов перед применением распараллеливания: #pragma omp for collapse (2)? –

0

Предполагая, что вы имеете в виду, чтобы иметь пару петель, содержащихся в одном OMP параллельно, это может быть разумным способом, чтобы избежать работы дисбаланса. Тем не менее я не вижу, что это гарантирует многое. Вы можете поместить внешний цикл по количеству потоков и вычислить количество итераций для цикла i, который точно уравновешивает количество элементов массива, заданных каждым потоком. Это может быть более эффективным способом поддержания местоположения NUMA, если это важно для вашей цели.

Смежные вопросы