我正在尝试编写一个计算两个大型密集矩阵的乘积的程序。当我使用尺寸为200 x 200的矩阵时,程序工作正常,但是当我转到300 x 300时,我得到一个弹出窗口,说“Assignment2.exe已停止工作......”我运行了调试器,我得到了这个错误消息:“程序收到信号SIGSEGV,分段错误。”
我知道显而易见的罪魁祸首是矩阵的大小太大,但我想知道是否有任何方法可以优化我的程序,以便它可以处理更大的矩阵(不更改函数原型,因为这些是设置的在石头上进行任务)。在MATLAB中,我能够处理比这更大的矩阵。我感谢您的帮助。谢谢!
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <random>
using namespace std;
int matrix_multiply(int n1, int n2, int n3, double *a, double *b, double *c);
int matrix_fill_random(int n1, int n2, double *a);
int matrix_print(int n1, int n2, double *a);
int matrix_multiply(int n1, int n2, int n3, double *a, double *b, double *c)
{
int i;
int j;
int k;
for (i=0;i<n1;i++) {
for (j=0;j<n3;j++) {
*(c+(i*n3)+j) = 0;
for (k=0;k<n2;k++) {
*(c+(i*n3)+j) += (*(a+(i*n2)+k) * (*(b+(k*n3)+j)));
}
}
}
return 0;
}
int matrix_fill_random(int n1, int n2, double *a)
{
int i;
for (i=0;i<(n1*n2);i++) {
*(a+i) = rand() % 20001 - 10000;
*(a+i) /= 10000;
}
return 0;
}
int matrix_print(int n1, int n2, double *a)
{
int i;
int j;
cout << "\n" << endl;
for (i=0;i<n1;i++) {
for (j=0;j<n2;j++) {
if (*(a+(i*n2)+j) >= 0) {
cout << " ";
}
cout << *(a+(i*n2)+j) << "\t";
}
cout << " " << endl;
}
return 0;
}
int main() {
int numRowsA;
int numColsA;
int numColsB;
int numIterations;
int i;
srand((unsigned int)time(0));
cout << "Please enter in the number of rows for Matrix A: ";
cin >> numRowsA;
cout << "Please enter in the number of columns for Matrix A: ";
cin >> numColsA;
cout << "Please enter in the number of columns for Matrix B: ";
cin >> numColsB;
cout << "Please enter in the number of iterations for repeating the multiplication: ";
cin >> numIterations;
double A[numRowsA][numColsA];
double B[numColsA][numColsB];
double C[numRowsA][numColsB];
matrix_fill_random(numRowsA,numColsA,(&A[0][0]));
matrix_fill_random(numColsA,numColsB,(&B[0][0]));
clock_t beforeMult;
clock_t afterMult;
clock_t ticks;
float seconds;
float secondsPerIteration;
beforeMult = clock();
for (i=0;i<numIterations;i++){
matrix_multiply(numRowsA,numColsA,numColsB,(&A[0][0]),(&B[0][0]),(&C[0][0]));
delete C;
}
afterMult = clock();
ticks = afterMult - beforeMult;
seconds = (float(ticks))/numIterations;
secondsPerIteration = seconds/CLOCKS_PER_SEC;
cout << "The number of total clock ticks is: " << ticks << endl;
cout << "The number of ticks per multiplication is: " << seconds << endl;
cout << "The number of seconds per multiplication is: " << secondsPerIteration << endl;
delete A;
delete B;
delete C;
}
答案 0 :(得分:2)
这样做是完全错误的:
delete A;
delete B;
delete C;
由于A
,B
和C
在此创建:
double A[numRowsA][numColsA];
double B[numColsA][numColsB];
double C[numRowsA][numColsB];
并且这些行中没有new
。如果您没有致电new
来创建某些内容,则不应使用delete
。并且 IF 使用new
创建二维数组,您很可能需要使用循环为每行分配列,然后反过来使用它来删除它 - 在删除数组时使用delete []
。
上面的代码也不符合C ++标准,因为标准C ++中任何数组的大小必须是编译时常量。您正在从用户那里读取大小,因此大小显然不是编译时常量。使用大量的列和行可能会导致在堆栈上分配空间时出现问题,即使编译器允许它也是如此。大多数系统的默认值大约为1-4MB的堆栈大小(因此最多可以达到500k左右的最大值)。一旦你使用了它,它就是“游戏结束”,那时你无法做任何事情来恢复。所以最好避免耗尽堆栈。这带来了循环的想法,以分配适当的内存量。但是,我建议您使用std::vector
而不是原始指针或数组,如下所示:
std::vector<std::vector <double> > A;
A.resize(numrowsa);
for(int i = 0; i < numrowsa; i++)
{
A[i].resize(numcolsa);
}
同样适用于B和C.
答案 1 :(得分:0)
使用new
运算符为我工作,如下面的代码所示:
double *A = new double[numRowsA*numColsA];
double *B = new double[numColsA*numColsB];
double *C = new double[numRowsA*numColsB];