基于OpenMP实现的冒泡排序速度比串行版本慢是什么原因?
问题根因
- 错误嵌套并行区域:内层重复使用
#pragma omp parallel for,每轮外循环都会重新创建、销毁线程池,线程调度开销远大于排序计算开销,是耗时飙升的核心原因。 - 外循环并行错误:奇偶排序的外循环存在数据依赖,必须串行执行,外层多余的
#pragma omp parallel错误地并行化了串行逻辑,导致执行逻辑混乱,额外增加同步开销。 - 无效的reduction操作:对
first变量添加的reduction(+:first)完全无意义,first仅作为每轮循环的奇偶标记,不需要归约操作,额外增加了同步开销。 - 循环变量竞争:
i、j、first变量没有声明为私有,多线程下存在数据竞争,频繁的缓存同步进一步拖慢执行速度。
修复后的代码
#include <omp.h> #include <stdio.h> #include <stdlib.h> void swap(int *num1, int *num2) { int temp = *num1; *num1 = *num2; *num2 = temp; } int main (int argc, char *argv[]) { int SIZE = 5000; int A[SIZE]; for(int i=0;i<SIZE;i++) { A[i] = rand()%SIZE; } int N = SIZE; int i=0, j=0; int first; double start,end; start = omp_get_wtime(); // 仅创建一次线程池 #pragma omp parallel default(none) shared(A,N) private(i,j,first) { // 外循环必须串行,仅由单个线程执行 #pragma omp single nowait { for( i = 0; i < N; i++ ) { first = i % 2; // 复用已创建的线程池并行执行内层循环,不需要再加parallel #pragma omp for for( j = first; j < N-1; j += 2 ) { if( A[ j ] > A[ j+1 ] ) { swap( &A[ j ], &A[ j+1 ] ); } } } } } end = omp_get_wtime(); for(i=0;i<N;i++) { printf(" %d",A[i]); } printf("\n-------------------------\n Time Parallel= %f",(end-start)); return 0; }
效果说明
修复后5000元素排序的并行耗时会下降到和串行版本相当,当数据集规模超过10万以上时,并行版本的性能优势会明显体现。
内容的提问来源于stack exchange,提问作者user3052356
相关产品推荐
相关产品推荐

