Производительность - ключевой момент.
Рассмотрим следующую программу
#include <stdio.h>
#include <omp.h>
#define N 1000000
int a[N], sum;
int main(){
double begin, end;
begin=omp_get_wtime();
for(int i =0; i<N; i++)
sum+=a[i];
end=omp_get_wtime();
printf("serial %g\t",end-begin);
begin=omp_get_wtime();
# pragma omp parallel for
for(int i =0; i<N; i++)
# pragma omp atomic
sum+=a[i];
end=omp_get_wtime();
printf("atomic %g\t",end-begin);
begin=omp_get_wtime();
# pragma omp parallel for reduction(+:sum)
for(int i =0; i<N; i++)
sum+=a[i];
end=omp_get_wtime();
printf("reduction %g\n",end-begin);
}
При выполнении (gcc -O3 -fopenmp) выдает:
серийный 0,00491182 атомный 0,0786559 сокращение 0,001103
Так что примерно атомный = 20xserial = 80xreduction
«Редукция» должным образом использует параллелизм, и с 4-ядерным компьютером мы можем получить повышение производительности от 3 до 6 по сравнению с «последовательным».
Теперь «атомарный» в 20 раз длиннее «серийного». Как объяснялось в предыдущем ответе, сериализация обращений к памяти отключает параллелизм, но все обращения к памяти выполняются атомарными операциями. Эти операции требуют не менее 20-50 циклов на современных компьютерах и значительно замедляют работу при интенсивном использовании.