Я хотел бы воспользоваться 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.
Я думаю, что это может быть вызвано проблемой ложного обмена, но я не могу найти ее.
Вы должны настроить распределение итераций между потоками. С 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 представляет собой. Проверять, выписываться как оптимизировать этот тест и вы сможете отобразить почти точно оптимизации вашего кода.
Других решений пока нет …