1

为简单起见,假设我NM行都有一个矩阵向量。我正在使用 STLstd::accumulate来计算所有矩阵的总和。我传递了一个二进制函子,它接受两个矩阵(通过引用)并返回它们的总和(通过引用)。全面披露:我正在使用 libstdc++ 并行模式。在仿函数内部,我分别遍历行以计算总和。

尽管每个矩阵都太大而无法放入缓存中,但一行非常适合。因此,重新排序循环将是有利的,以便外部循环索引M行,而内部循环索引N矩阵。除了定义内联函子之外,我还能做些什么来鼓励这种跨功能边界循环重新排序。我当然可以重构代码,但理想情况下我希望保持使用 STL 算法提供的简单结构。如果有特定于 gcc 的东西,我也不介意。

我实际上并不是在处理矩阵,这只是一个例子,但同样的问题结构也适用。主要问题是性能问题。解释实际场景太麻烦了,但核心问题是:STL 的累加需要在嵌套循环之间进行排序,这对缓存不是很友好,因为它会在移动到下一个对象之前尝试完成两个对象的相加。单个对象太大而无法保存在缓存中,但它的一部分可以。因此,如果一次计算“加法”一个“部分”(在所有对象上),则可以加快执行速度。手动重新排序循环可以显着提高 FLOPS。但理想情况下,我希望编译器进行重新排序,以便我可以在 STL 级别(尽可能)进行编码。所以我正在寻找技巧来做到这一点。

4

3 回答 3

1

我无法想象编译器会解决这个问题,除非所有内容都被内联并且 M 和 N 是恒定的。即使那样,这也将是一个延伸。

为了保持 STL 算法风格,在累积上使用 foreach M 并让仿函数只对一行求和。

于 2010-12-17T02:53:59.560 回答
1

编写一个新算法,或者将内容包装在 for 循环或std::for_each()调用中。这将比寻找适应方法容易得多std::accumulate()。我认为这里唯一的其他选择是向库引入一个新的抽象级别,即超越迭代器。编写一个新算法或引入一个额外的循环更容易。

于 2010-12-17T03:32:33.153 回答
1
class Matrix;
class Row;
struct SumNRow {
  int _rowidx;
//  Row _tempRow; //For return by reference left out for simplicity
  SumNRow(int iRowIdx): _rowIdx(iRowIdx) {}
  Row operator(const Matrix & iMarix1, const Matrix iMatrix2) {
    return iMarix1[_rowIdx] + iMatrix2[_rowIdx];
  }
};

template<class MatrixIterator>
void sum(const MatrixIterator & iMarixStart, const MatrixIterator & iMatrixEnd, Matrix & oMarix) {
  for (int i = 0; i < iMarixStart->rowCount(); ++i) {
    oMarix[i]=std::accumulate(iMarixStart, iMatrixEnd, SumNRow(i));
  }
}
于 2010-12-17T04:52:33.600 回答