进行矩阵乘法时C++中的分段错误

Segmentaion fault in C++ when doing matrix multiplication

本文关键字:C++ 分段 错误      更新时间:2023-10-16

>我在下面有一个程序,它应该根据不同的索引分析矩阵乘法的时间。但是一些函数给出了分割错误,其中两个是matmul_kji(C,A,B)和matmul_jki(C,A,B)。有人可以向我解释我做错了什么以及可能的改进。此代码应检查从 (1000*1000) 到 (10000*10000) 的矩阵时序。

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include <sys/time.h>  
using namespace std;
# define MATSIZE 1000

double get_wall_time(){
    struct timeval time;
    if (gettimeofday(&time,NULL)){
        //  Handle error
        return 0;
    }
    return (double)time.tv_sec + (double)time.tv_usec * .000001;
}
double get_cpu_time(){
    return (double)clock() / CLOCKS_PER_SEC;
}  
void init_mat ( double M[MATSIZE][MATSIZE])
{
int i, j;
for (i=0; i<MATSIZE; i++) {
for (j=0; j<MATSIZE; j++) {
M[i][j] = sin(double(i));
}
}
}
void matmul_ijk ( double C[MATSIZE][MATSIZE],
double A[MATSIZE][MATSIZE], double B[MATSIZE][MATSIZE]) //1
{
int i, j, k;        
double aux;
double cpu0 = get_cpu_time();
for (i=0; i<MATSIZE; i++) {
for (j=0; j<MATSIZE; j++) {
aux = 0;
for (k=0; k<MATSIZE; k++) {
aux += A[i][k] *B[k][j];
}
C[i][j] += aux;
}
}
double cpu1 = get_cpu_time();
cout << "CPU Time Of IKJ Ordering = "<< cpu1-cpu0<<endl;
}                      
void matmul_ikj ( double C[MATSIZE][MATSIZE],
double A[MATSIZE][MATSIZE], double B[MATSIZE][MATSIZE]) //2
{
int i, j, k;        
double aux;
double cpu0 = get_cpu_time();
for (i=0; i<MATSIZE; i++) {
for (k=0; k<MATSIZE; k++) {
aux = 0;
for (j=0; j<MATSIZE; j++) {
aux += A[i][k] *B[k][j];
}
C[i][j] += aux;
}
}
double cpu1 = get_cpu_time();
cout << "CPU Time Of IKJ Ordering = "<< cpu1-cpu0<<endl;
}         
void matmul_kij ( double C[MATSIZE][MATSIZE],
double A[MATSIZE][MATSIZE], double B[MATSIZE][MATSIZE])  //3
{
int i, j, k;        
double aux;
double cpu0 = get_cpu_time();
for (k=0; k<MATSIZE; k++) {
for (i=0; i<MATSIZE; i++) {
aux = 0;
for (j=0; j<MATSIZE; j++) {
aux += A[i][k] *B[k][j];
}
C[i][j] += aux;
}
}
double cpu1 = get_cpu_time();
cout << "CPU Time of KIJ ordering = "<< cpu1-cpu0<<endl;
}                      
void matmul_kji( double C[MATSIZE][MATSIZE],
double A[MATSIZE][MATSIZE], double B[MATSIZE][MATSIZE]) //4
{
int i, j, k;        
double aux;
double cpu0 = get_cpu_time();
for (k=0; k<MATSIZE; k++) {
for (j=0; j<MATSIZE; j++) {
aux = 0;
for (i=0; i<MATSIZE; i++) {
aux += A[i][k] *B[k][j];
}
C[i][j] += aux;
}
}
double cpu1 = get_cpu_time();
cout << "CPU Time Of IKJ Ordering = "<< cpu1-cpu0<<endl;
}                      

void matmul_jik( double C[MATSIZE][MATSIZE],
double A[MATSIZE][MATSIZE], double B[MATSIZE][MATSIZE])   //5
{
int i, j, k;        
double aux;
double cpu0 = get_cpu_time();
for (j=0; j<MATSIZE; j++) {
for (i=0; i<MATSIZE; i++) {
aux = 0;
for (k=0; k<MATSIZE; k++) {
aux += A[i][k] *B[k][j];
}
C[i][j] += aux;
}
}
double cpu1 = get_cpu_time();
cout << "CPU Time Of KJI Ordering = "<< cpu1-cpu0<<endl;
}      
void matmul_jki ( double C[MATSIZE][MATSIZE],
double A[MATSIZE][MATSIZE], double B[MATSIZE][MATSIZE])   //6
{
int i, j, k;        
double aux;
double cpu0 = get_cpu_time();
for (j=0; j<MATSIZE; j++) {
for (k=0; k<MATSIZE; k++) {
aux = 0;
for (i=0; i<MATSIZE; i++) {
aux += A[i][k] *B[k][j];
}
C[i][j] += aux;
}
}
double cpu1 = get_cpu_time();
cout << "CPU Time Of JKI Ordering = "<< cpu1-cpu0<<endl;
}                   
/*void matmul_ikj( double C[MATSIZE][MATSIZE],              
double A[MATSIZE][MATSIZE], double B[MATSIZE][MATSIZE])
{
int i, j, k;        
double aux;
double cpu0  = get_cpu_time();
for (i=0; i<MATSIZE; i++) {
for (k=0; j<MATSIZE; j++) {
aux = 0;
for (j=0; k<MATSIZE; k++) {
aux += A[i][k]*B[k][j];
}
C[i][j] += aux;
}
}
double cpu1  = get_cpu_time();
cout << "CPU Time  = " << cpu1  - cpu0  << endl;
} */         
int main ()
{
static double A[MATSIZE][MATSIZE];
static double B[MATSIZE][MATSIZE];
static double C[MATSIZE][MATSIZE]= {{0}};
init_mat (A);
init_mat (B);
//matmul_ijk(C,A,B);
//matmul_ikj(C,A,B);  
//matmul_kij(C,A,B);
matmul_kji(C,A,B);      // Gives a segmentation error
//matmul_jik(C,A,B);
matmul_jki(C,A,B);    // Gives a segmentation error
/*for (int i=0; i<10; i++){
    for(int j=0; j < 10; j++){
        cout << C[i][j]<<"  ";
    }
    cout <<endl; } */      
return 0;
}                  

这是问题所在:

C[i][j] += aux; // Inside matmul_kji

这是在两个嵌套循环中执行的,变量为 jk,而不是 ij ,所以它应该是

C[j][k] = aux;

请注意,您需要将+=替换为 = ,因为所有添加都是由第三个嵌套循环完成的。

另请注意,如果您使用现代 * 方式定义循环变量,编译器可以帮助您避免此类问题:与其预先定义它们,不如在循环标头中定义它们,如下所示:

for (int k=0; k<MATSIZE; k++) {
    for (int j=0; j<MATSIZE; j++) {
        double aux = 0;
        for (int i=0; i<MATSIZE; i++) {
            aux += A[i][k] *B[k][j];
        }
        C[i][j] += aux; // <<== Compile error!
    }
}


*"现代"是非常相对的:这种声明循环变量的方式自八十年代中期以来就已经存在,使其相当古老。
对于

未在外部循环中设置i的两种情况,您可能会遇到分段错误,因为

C[i][j] += aux;