#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. Конечно, но увеличение количества потоков ничего ему не даст, если он на самом деле насыщает контроллер памяти.