Ложный обмен в доступе к массиву петель OpenMP

Я хотел бы воспользоваться OpenMP, чтобы сделать мою задачу параллельной.

Мне нужно вычесть одно и то же количество для всех элементов массива и записать результат в другом векторе. Оба массива динамически распределяются с malloc и первый заполнен значениями из файла. Каждый элемент имеет тип uint64_t,

#pragma omp parallel for
for (uint64_t i = 0; i < size; ++i) {
new_vec[i] = vec[i] - shift;
}

куда shift это фиксированное значение, которое я хочу удалить из каждого элемента vec, size длина обоих vec а также new_vec, что примерно 200к.

Я компилирую код с g++ -fopenmp на Arch Linux. Я на Intel Core i7-6700HQ, и я использую 8 потоков. Время работы в 5-6 раз выше, когда я использую версию OpenMP. Я вижу, что все ядра работают, когда я запускаю версию OpenMP.

Я думаю, что это может быть вызвано проблемой ложного обмена, но я не могу найти ее.

1

Решение

Вы должны настроить распределение итераций между потоками. С schedule(static,chunk_size) Вы можете сделать это.

Попробуйте использовать значения chunk_size, кратные 64 / sizeof (uint64_t), чтобы избежать ложного совместного использования:

[ cache line n   ][ cache line n+1 ]
[ chuhk 0  ][ chunk 1  ][ chunk 2  ]

И добиться чего-то вроде этого:

[ cache line n   ][ cache line n+1 ][ cache line n+2 ][...]
[ chunk 0                          ][ chunk 1             ]

Вы также должны распределить свои векторы таким образом, чтобы они были выровнены по строкам кэша. Таким образом вы гарантируете, что первый и последующие фрагменты также будут правильно выровнены.

#define CACHE_LINE_SIZE sysconf(_SC_LEVEL1_DCACHE_LINESIZE)
uint64_t *vec = aligned_alloc( CACHE_LINE_SIZE/*alignment*/, 200000 * sizeof(uint64_t)/*size*/);

Ваша проблема действительно похожа на то, что Тест Stream Triad представляет собой. Проверять, выписываться как оптимизировать этот тест и вы сможете отобразить почти точно оптимизации вашего кода.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]