OpenMP: ускорят ли циклы разные ячейки памяти?

#loops #for-loop #openmp

#циклы #для цикла #openmp

Вопрос:

У меня есть программа OpenMP, которая вычисляет переменные в цикле.

 int a[1000000];
int b[1000000];
int c[1000000];
int d[1000000];

#pragma omp parallel for private(i) shared(a,b,c,d)
for (i=0;i<1000000;  i)
{
d[i] = b[i]*a[i]   c[i] 10;
}
  

Я использовал perf, и perf сказал, что узким местом является чтение и запись в память.

Первый вопрос: Возможно ли разделить массивы A, B, C, D и поместить их в разные банки памяти с помощью OpenMP?

Второй вопрос: Если я разделю массивы A, B, C, D на меньшие массивы, ускорят ли они выполнение цикла?

Комментарии:

1. Вы могли бы использовать структуру с a, b, c, d, чтобы повысить эффективность кэширования.

2. Выравнивание @H4kor, похоже, ускоряет его на 10%. Но эффективность (ускорение / процессоры) по-прежнему низкая < 50%.

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

4. Очевидно, что этот цикл следует векторизовать (перед распараллеливанием, поскольку векторизация может сократить требуемое процессорное время, в то время как распараллеливание просто перемещает его, чтобы быстрее получить ответ), поэтому в вашей директиве используйте «simd » после «for». Но, поскольку это связано с BW (как все говорят), это может не иметь большого значения. (И при векторизации вам не нужен массив структур!)

5. Статическое расписание по умолчанию с максимальными порциями по сути сохраняет потоки на разных страницах. Если на платформе NUMA вы должны соблюдать постоянный доступ в 1-е касание, чтобы избежать удаленного доступа к памяти

Ответ №1:

  • Первый вопрос: Возможно ли разделить массивы A, B, C, D и поместить их в разные банки памяти с помощью OpenMP?

Насколько мне известно, нет, вы не можете явно разделять массивы с помощью функций среды выполнения OpenMP. Что делает OpenMP, так это приписывает равную нагрузку на каждый поток. Допустим, вы определили OMP_NUM_THREADS= 10, тогда каждый поток получит 100000 итераций для выполнения. Или последний поток получит меньше работы, если остаток не равен 0. (Что вы можете сделать, так это назначить привязку потоков к ядрам.)

  • Второй вопрос: Если я разделю массивы A, B, C, D на меньшие массивы, ускорят ли они выполнение цикла?

Нет. Но вы можете увеличить количество потоков для повышения производительности (до тех пор, пока накладные расходы потоков не превысят ускорение)

Комментарии:

1. В его случае это ничего не даст.

2. @Qubit, он задал два вопроса, он ожидает несколько правильных ответов? Или я что-то упускаю?

3. Конечно, но увеличение количества потоков ничего ему не даст, если он на самом деле насыщает контроллер памяти.