并行计算mvir累积概率分布时并行与串行运行结果不一致问题
问题产生原因
- 核心问题是数据竞争:你定义的
cuenta变量是所有OpenMP线程共享的变量,多线程同时执行cuenta++操作时,会出现多个线程同时读取同一个cuenta值、各自加1后回写的情况,导致大量计数被覆盖丢失,最终结果和串行执行不一致。 - OpenMP默认会把并行区域外定义的变量视为共享变量,你没有对计数变量做归约或者私有声明,就会触发这个问题。
修复方案
只需要给#pragma omp parallel for指令增加reduction(+:cuenta)子句即可。OpenMP会自动为每个线程创建独立的cuenta私有副本,并行循环执行结束后,自动把所有线程的私有副本数值累加,写入原cuenta变量,完全避免数据竞争。
修复后的代码如下:
vector<double> mvir, contador; double mlimite; for (int i = 0; i != mvir.size() - 1; i++) { mlimite = mvir[i]; int cuenta = 0; // 建议把cuenta的定义放在此处,作用域更清晰,避免变量污染 #pragma omp parallel for reduction(+:cuenta) for (int j = 0; j != mvir.size() - 1; j++) { if (mvir[j] >= mlimite) { cuenta++; } } contador.push_back(cuenta); }
可选优化建议:当前实现的时间复杂度为O(n²),数据量大时效率很低。你可以先对mvir数组做升序排序,对于每个阈值
mlimite = mvir[i],直接用二分查找找到第一个大于等于mlimite的元素下标,mvir.size() - 下标就是符合要求的数量,复杂度可降到O(n logn),远快于并行优化后的O(n²)实现。
内容的提问来源于stack exchange,提问作者Elena
相关产品推荐
相关产品推荐

