1

N簡単にするために、各行の行列のベクトルがあると仮定しMます。STLstd::accumulateを使用して、すべての行列の合計を計算しています。2 つの行列を (参照により) 受け取り、それらの合計を (参照により) 返すバイナリ ファンクターを渡します。完全な開示: libstdc++ 並列モードを使用しています。ファンクター内では、行を個別にループして合計を計算します。

各マトリックスは大きすぎてキャッシュに収まりませんが、行は非常にうまく収まります。そのため、ループの順序を変更して、外側のループがM行にインデックスを付け、内側のループがN行列にインデックスを付けるようにすることをお勧めします。ファンクターをインラインで定義することに加えて、このようなクロス関数境界ループの並べ替えを促進するために他にできることはありますか? もちろん、コードを再構築することもできますが、理想的には、STL アルゴリズムを使用できる単純な構造を維持したいと考えています。gcc 固有のものがあれば、それも気にしません。

私は実際に行列を扱っているわけではありません。これは単なる例ですが、同じ問題構造が適用されます。主な問題はパフォーマンスの問題です。実際のシナリオを説明するのは面倒ですが、核となる問題は次のとおりです。STL のアキュムレートは、次のオブジェクトに移動する前に 2 つのオブジェクトの追加を完了しようとするため、ネストされたループ間の順序付けを伴います。これはキャッシュ フレンドリーではありません。1 つのオブジェクトは大きすぎてキャッシュに保持できませんが、一部は保持できます。そのため、(すべてのオブジェクトに対して) 一度に 1 つの「部分」の「加算」を計算すると、実行を高速化できます。ループを手動で並べ替えると、FLOPS が大幅に改善されます。しかし、可能な限り STL レベルでコーディングできるように、コンパイラーに並べ替えを実行してもらいたいと考えています。だから私はこれを行うためのトリックを探しています。

4

3 に答える 3

1

すべてがインライン化されていて、M と N が一定でない限り、コンパイラがこれを理解することは想像できません。それでも、それはストレッチになります。

STL アルゴリズム スタイルを維持するには、累積に対して foreach M を使用し、ファンクターで行を合計するだけにします。

于 2010-12-17T02:53:59.560 に答える
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 に答える
1

新しいアルゴリズムを作成するか、for ループまたはstd::for_each()呼び出しでラップします。適応する方法を見つけるよりもはるかに簡単ですstd::accumulate()。ここでの唯一の代替案は、イテレータを超えた新しい抽象化レベルをライブラリに導入することだと思います。新しいアルゴリズムを書くか、追加のループを導入する方が簡単です。

于 2010-12-17T03:32:33.153 に答える