我有一个 C++ 类,其中包含表示预设长度 vector 的结构和预设大小的矩阵。每个 vector 只是一个 double 组,每个矩阵都是一个 vector 数组。我选择不使用 C++ 提供的 Vector 类,因为我根本不需要调整 vector 的大小,也不会使用 vector 的任何实例方法。我只是在寻找我的双数组的包装器。
这个类的目标是通过将矩阵分解成更小的 block 来执行 2 个大矩阵 (512x512) 的矩阵乘法,然后使用 MPI 在我们本地计算集群上的多个节点上执行乘法。当我试图将矩阵分解成更小的 block 时,我遇到了堆栈溢出异常的问题。这是一些代码:
// Vector Structs
struct Vec512 { double values[512]; };
struct Vec256 { double values[256]; };
struct Vec128 { double values[128]; };
struct Vec64 { double values[64]; };
// Matrix Structs
struct Mat512 {
Vec512 rows[512];
Mat512(){}
Mat512(MatrixInitEnum e){
switch(e){
case Empty:
for(int row = 0; row < 512; row++){
Vec512 temp;
for(int col = 0; col < 512; col++){
temp.values[col] = 0;
}
rows[row] = temp;
}
break;
case Random:
for(int row = 0; row < 512; row++){
Vec512 temp;
for(int col = 0; col < 512; col++){
temp.values[col] = myRandom();
}
rows[row] = temp;
}
break;
}
}
Vec512 GetRow(int row){
return rows[row];
}
Vec512 GetColumn(int col){
Vec512 column;
for(int i = 0; i < 512; i++){
column.values[i] = rows[i].values[col];
}
return column;
}
void SetValue(int row, int col, double value){
rows[row].values[col] = value;
}
double GetValue(int row, int col){
return rows[row].values[col];
}
};
// Analogous structs for Mat256, Mat128, Mat64
/*Decomposes the big matrix into 4 256x256 matrices in row-major fashion*/
Mat256* DecomposeMatrix256(Mat512 *bigMat){
Mat256 matArray[4];
int beginRow, endRow, beginCol, endCol, rowOffset, colOffset;
for(int it = 0; it < 4; it++){
beginRow = (it/2) * 256;
endRow = beginRow + 256;
beginCol = (it % 2) * 256;
endCol = beginCol + 256;
rowOffset = (it / 2) * 256;
colOffset = (it % 2) * 256;
for(int row = beginRow; row < endRow; row++){
for(int col = beginCol; col < endCol; col++){
double val = bigMat->GetValue(row, col);
matArray[it].SetValue(row - rowOffset, col - colOffset, val);
}
}
}
return matArray;
}
// Analogous methods for breaking into 16 128x128 Mat128s and 64 64x64 Mat64s
然后我的主要方法很简单
int main(int argc, char* argv[])
{
cout << "Welcome, the program is now initializing the matrices.\n";
Mat512* bigMat = new Mat512(Random); // Creates this just fine
Mat256* mats256 = DecomposeMatrix256(bigMat); // Gets here and can step to the signature of the method above without issue
// MPI code to split up the multiplication and to
// wait until user is ready to exit
return 0;
}
这是我的问题: 我可以用我的随机值创建大 Mat512 没问题。我在创建大矩阵的地方设置了一个断点,并验证它正在创建成功。然后我进入对 DecomposeMatrix256(Mat512 * bigMat) 的调用,发现我正在使用该方法没有问题。此外,当鼠标悬停在 bigMat 对象上时,visual studio 向我显示它确实在接收 big 矩阵。当我尝试进入该方法时,立即出现堆栈溢出异常。
令我感到困惑的是,为什么我什至在创建另一个新对象(例如 4 个 256x256 矩阵的数组)之前就会发生堆栈溢出。我很确定我通过引用而不是通过值传递矩阵(我习惯了 C# 而不是 C++ 所以我很高兴听到我只是在引用传递上做错了)所以我认为不会'简单地传递对大矩阵的引用是一个很大的开销。
我能够通过进入项目配置设置并将堆栈保留大小从 1MB(默认值)增加到 8MB(可能有点矫枉过正,但我只是想让它用于我的调试目的)来解决我的问题。
有人可以解释为什么当我只是传递对大矩阵的引用而不是矩阵本身(按值)时会出现溢出吗?同样,我通过增加堆栈大小使其工作,但我不明白为什么当我通过引用而不是通过值传递对象时有必要这样做。
感谢阅读和输入。我很乐意发布与帮助理解我的问题相关的任何其他信息。
最佳答案
DecomposeMatrix256()
在堆栈上创建一个包含四个 Mat256
对象的数组。这很可能导致溢出,因为它需要大量堆栈空间。您传递的参数不是溢出的原因。
作为另一个问题,该函数返回一个指向局部变量的指针,该变量将在函数结束时超出范围。此指针将不再指向有效对象。
关于c++ - 通过引用传递大对象时堆栈溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22272543/