OpenMP矩阵乘法C程序输出空白及rand警告问题求助
你的OpenMP矩阵乘法程序问题排查与修复
我帮你梳理下程序里的几个关键问题,这些问题直接导致了rand函数的警告、输出空白,还有结果不正确的情况:
1. rand函数隐式声明警告
你看到的rand()隐式声明警告,是因为这个函数的定义在<stdlib.h>头文件里,而你没有包含它。只要在代码开头加上:
#include <stdlib.h>
就能彻底消除这个警告了。
2. 输出空白的直接原因
你的结果输出循环里有个致命的逻辑错误:
for( j =0 ; j < k ; j ++)
这里的k是你在并行区域里声明的私有变量(private(i,j,k)),并行循环结束后,主线程里的k值是未定义的(可能是0或者随机的垃圾值),导致这个j循环根本不会执行,自然输出就是一片空白。
你应该把循环条件改成矩阵的列数NCB,也就是:
for( j =0 ; j < NCB ; j ++)
另外,考虑到500×500的矩阵输出量极大,建议只输出前几行几列(比如前5行5列),否则输出会非常缓慢,甚至刷屏半天。
3. 矩阵乘法的核心逻辑错误
除了输出问题,你的乘法计算逻辑也完全不对,这会导致结果完全无效:
- mat3未初始化:局部数组
mat3[NRA][NCB]的默认值是随机垃圾值,你直接用+=累加,结果肯定是错的。必须在计算前把所有元素初始化为0:// 在并行区域前初始化mat3 for (int i = 0; i < NRA; i++) { for (int j = 0; j < NCB; j++) { mat3[i][j] = 0; } } - 乘法索引错误:正确的矩阵乘法公式是
mat3[i][j] += mat1[i][k] * mat2[k][j],但你写的是mat3[i][k] += mat1[i][k] * mat2[k][j],索引完全混乱,这会导致计算出来的mat3根本不是两个矩阵的乘积。 - k循环范围错误:矩阵乘法中,中间循环的范围应该是第一个矩阵的列数(也就是
NCA),而不是第二个矩阵的列数NCB。你之前写的k < NCB是错的,应该改成k < NCA。 - mat1和mat2的初始化问题:你在同一个循环里给
mat1[i][j]和mat2[i][j]赋值,虽然当前三个宏都是500不会越界,但逻辑上mat2的行维度是NCA,如果后续修改宏的值,很容易出现数组越界。建议分开初始化两个矩阵:// 初始化mat1 for (int i = 0; i < NRA; i++) { for (int j = 0; j < NCA; j++) { mat1[i][j] = rand(); } } // 初始化mat2 for (int i = 0; i < NCA; i++) { for (int j = 0; j < NCB; j++) { mat2[i][j] = rand(); } }
4. 其他小建议
- 尽量避免使用全局变量(比如你定义的全局
i,j,k),把变量声明在函数内部,这样更安全,也符合现代C语言的编码规范。 - 并行区域的
#pragma omp for放在i循环上是合理的,因为每个线程负责独立的行,不会有数据竞争问题,这点你做的是对的。
最后,给你一个修复后的核心代码片段参考:
#include <stdio.h> #include <omp.h> #include <time.h> #include <stdlib.h> // 新增头文件 #define NRA 500 #define NCA 500 #define NCB 500 int mat_mul(); int main(){ double start , end ; start = omp_get_wtime() ; mat_mul() ; end = omp_get_wtime() ; printf("\nTime taken : %lf\n" , (end - start) ); return 0; } int mat_mul(){ int mat1[NRA][NCA] , mat2[NCA][NCB] , mat3[NRA][NCB] ; int i , j , k ; // 初始化mat3为0 for (i = 0; i < NRA; i++) { for (j = 0; j < NCB; j++) { mat3[i][j] = 0; } } // 初始化mat1 for (i = 0; i < NRA; i++) { for (j = 0; j < NCA; j++) { mat1[i][j] = rand(); } } // 初始化mat2 for (i = 0; i < NCA; i++) { for (j = 0; j < NCB; j++) { mat2[i][j] = rand(); } } #pragma omp parallel private( i , j , k ) shared(mat1 , mat2 , mat3) #pragma omp for for( i = 0 ; i < NRA ; i++){ for( j = 0 ; j < NCB ; j++){ for ( k = 0 ; k < NCA ; k++){ // 修正k的循环范围 mat3[i][j] += mat1[i][k] * mat2[k][j] ; // 修正索引逻辑 } } } printf("Result (first 5x5): \n"); // 只输出前5行5列,避免输出过多 for( i = 0 ; i < 5 ; i ++ ) { for( j =0 ; j < 5 ; j ++){ printf("%d " , mat3[i][j]); } printf("\n") ; } return 0 ; }
内容的提问来源于stack exchange,提问作者Tejas Garhewal
相关产品推荐
相关产品推荐

