【发布时间】:2014-04-11 22:12:57
【问题描述】:
我有一个 c++ 类,它包含表示预设长度的向量和预设大小的矩阵的结构。每个向量只是一个双精度数组,每个矩阵都是一个向量数组。我选择不使用 C++ 提供的 Vector 类,因为我根本不需要调整向量的大小,也不会使用向量的任何实例方法。我只是在寻找我的双数组的包装器。
本课程的目标是执行 2 个大矩阵 (512x512) 的矩阵乘法,方法是将矩阵分解为更小的块,然后使用 MPI 在本地计算集群上的多个节点上执行乘法运算。当我试图将矩阵分解成更小的块时,我遇到了堆栈溢出异常的问题。这是一些代码:
// 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 向我显示它确实在接收大矩阵。当我尝试单步进入该方法时,我立即得到了堆栈溢出异常。
我感到困惑的是,为什么我什至在创建另一个新对象(如 4 个 256x256 矩阵的数组)之前就会发生堆栈溢出。我很确定我是通过引用而不是值传递矩阵(我习惯于 C# 而不是 C++,所以我很高兴听到我只是在引用传递时做错了)所以我认为不会简单地传递对大矩阵的引用是一个很大的开销。
我能够通过进入项目配置设置并将堆栈保留大小从 1MB(默认值)增加到 8MB(可能有点矫枉过正,但我只是希望它用于我的调试目的)来解决我的问题。
有人可以解释为什么我只是传递对大矩阵的引用而不是矩阵本身(按值)时会出现溢出吗?同样,我通过增加堆栈大小使其工作,但我不明白为什么当我通过引用而不是通过值传递对象时这是必要的。
感谢您的阅读和输入。我很乐意发布与帮助理解我的问题相关的任何其他内容。
【问题讨论】:
-
可能不相关:您在
getRow中返回副本 - 返回引用可能更好更快 -
谢谢,这是一个有效的观点。我会尝试改变它,看看它是否有帮助。我犹豫是否认为这是整体问题,因为当我遇到溢出时我不会调用该方法。
标签: c++ matrix stack-overflow