OpenMP临界区实现矩阵乘法结果不符原因排查
问题根源分析
你的临界区实现结果完全不正确,核心原因有以下几点:
1. 并行区域位置严重错误
你在最内层k循环前加#pragma omp parallel for,意味着每处理一个(i,j)元素对,就会创建一个全新的OpenMP并行区域。假设SIZE为1000,程序会尝试创建1000×1000=100万个并行区域——这会彻底打乱线程调度逻辑,导致系统线程资源耗尽,计算过程出现不可控的异常,最终结果完全错误。
这种用法完全违背OpenMP的设计原则,并行区域应尽量放在外层循环,避免重复创建、销毁线程带来的开销和混乱。
2. 矩阵初始化大概率未正确处理
你的单线程代码是对C[i][j]做累加操作,这要求计算前C矩阵必须初始化为全0。如果并行版本中C矩阵未做初始化(保留内存垃圾值),累加后的结果必然和单线程正确初始化的D矩阵完全不匹配,导致验证用的correct变量始终为0。
3. 代码存在语法错误
你提供的并行代码末尾多了一个冗余的},这会导致编译错误。如果实际运行的代码存在这个问题,程序根本无法正常执行,结果自然不正确。
临界区写法的正确示例(仅作学习参考,性能极差)
如果一定要用临界区实现(性能远不如单线程,仅用于理解逻辑),应将并行区域放到最外层循环,避免重复创建线程:
#pragma omp parallel shared(A, B, C) private(i, j, k, tmp) { #pragma omp for for (i = 0; i < SIZE; i++) for (j = 0; j < SIZE; j++) for (k = 0; k < SIZE; k++) { tmp = A[i][k] * B[k][j]; #pragma omp critical { C[i][j] += tmp; } } }
注:临界区会导致全局锁竞争,实际场景中应使用reduction子句或分块并行(让每个线程独立负责一部分矩阵元素,完全避免临界区)来实现高效并行。
内容的提问来源于stack exchange,提问作者BrightSoul
相关产品推荐
相关产品推荐

