Боюсь, ваше предположение неверно.Версия с критическим разделом действительно дает правильный ответ - по крайней мере, не детерминированный ответ.
Для простоты возьмем случай, когда get_key
всегда возвращает 0
.Последовательная версия будет копировать массив, параллельная - произвольную перестановку.Между всеми итерациями существует упорядоченная зависимость, в которой get_key
возвращает одно и то же значение.
Вообще говоря.Простые критические секции часто могут быть заменены сокращением, которое обеспечивает независимое выполнение, в то же время вызывая некоторые издержки слияния после параллельной части.Atomics также может быть вариантом для простых операций, но они также страдают от общего снижения производительности и часто дополнительных проблем с кешем.Технически ваш неверный код критической секции будет эквивалентен этому чуть более эффективному атомарному коду:
int index;
#pragma omp atomic capture
index = count[key]++;
#pragma omp atomic write
toArray[index] = fromArray[i];
Интересно, есть ли способ распараллелить его с хорошей производительностью?
Любой вопрос о производительности требует более конкретной информации.Какие существуют типы, размеры данных, уровень параллелизма, ...?Нет общего ответа на «это лучший способ повышения производительности» .