如何实现2D矩阵原地重排,降低低端设备运行内存开销?
结论
可以实现,仅需常数级额外空间即可完成原地重排,完全消除coef数组的内存开销。
原逻辑本质分析
你提供的重排代码本质是对**R行(R = _numEquations)2列的列主序矩阵_matrixCoef**做转置,最终得到2行R列的矩阵,原coef[iRHS][iRow]等价于转置后矩阵的(iRHS, iRow)位置元素。
转置前后矩阵总元素数均为2*R,_matrixCoef底层的vector存储空间可以完全复用,不需要申请额外的堆内存块。
实现方案
根据后续的访问方式,可以选择两种不同的优化方案,都符合原地重排的要求:
方案1:后续仍按coef[iRHS][iRow]方式访问
不需要做任何元素重排,也不需要修改矩阵属性,直接复用矩阵底层数组指针即可,额外开销几乎为0:
// 仅在栈上申请两个指针,占用空间可忽略 double* coef[NUM_VARS]; coef[0] = _matrixCoef.data(); coef[1] = _matrixCoef.data() + _matrixCoef.getNumRows();
由于原矩阵是列主序存储,第iRHS列的元素在底层数组中是连续存储的,刚好对应coef[iRHS]指向的一维数组,和原重排后的coef访问逻辑完全一致。
方案2:后续需要通过Matrix的(row, col)运算符访问转置后的矩阵
需要调整元素存储顺序并修改矩阵属性,仅需1个临时double变量做交换缓存,额外空间开销为O(1):
const int row_count = _matrixCoef.getNumRows(); double* const data_ptr = _matrixCoef.data(); // 原地调整元素顺序,适配列主序2行N列矩阵的访问规则 for (int i = row_count - 1; i > 0; --i) { double temp = data_ptr[row_count + i]; for (int k = 0; k < i; ++k) { data_ptr[row_count + i - k] = data_ptr[row_count + i - k - 1]; } data_ptr[2 * i] = temp; } // 更新矩阵的行列属性,完成转置 _matrixCoef.resize(2, row_count);
调整完成后,_matrixCoef(iRHS, iRow)的返回值和原coef[iRHS][iRow]完全一致。
内容的提问来源于stack exchange,提问作者benjist
相关产品推荐
相关产品推荐

