1

私のアルゴリズムのボトルネックは、KPro と呼ばれる関数 Kronecker Product です。

gsl_matrix *KPro(gsl_matrix *a, gsl_matrix *b) {
    int i, j, k, l;
    int m, p, n, q;
    m = a->size1;
    p = a->size2;
    n = b->size1;
    q = b->size2;

    gsl_matrix *c = gsl_matrix_alloc(m*n, p*q);
    double da, db;

     for (i = 0; i < m; i++)    {
          for (j = 0; j < p; j++)   {
              da = gsl_matrix_get (a, i, j);
              for (k = 0; k < n; k++)   {
                  for (l = 0; l < q; l++)   {
                      db = gsl_matrix_get (b, k, l);
                      gsl_matrix_set (c, n*i+k, q*j+l, da * db);                
                  }
              }
          }
      }

    return c;
}

GSL を使用した効率的な実装を知っていますか? 適切なルーチンが見つかりません。

4

2 に答える 2

0

キャッシュメモリを「ブロック」してより効果的に利用することで、パフォーマンスを大幅に向上させることができます。

この論文を見てください。簡単にCコードに変換できると思う擬似コードがあります。また、キャッシュサイズとマトリックスパラメータを指定して最適なブロックサイズを把握するためのアルゴリズムもあります。

于 2012-12-05T20:33:08.340 に答える
0

表面的に見ただけで、あなたのルーチンには多くの潜在的なボトルネックがあることがわかります:

  1. 毎回再割り当てするのではなく、行列 c を再利用します。つまり、関数スタック変数からクラス メンバーに、または静的ファイルにプロモートします。可能な限り最大の問題サイズまで一度に割り当てます。
  2. これらすべての gsl_matrix_get および gsl_matrix_set を呼び出すと、コンパイラがコードを自動ベクトル化するのを確実に防ぎます。代わりに、オーバーロードまたはインライン化された演算子と直接メモリ アクセスを使用したテンプレート ベースのマトリックス実装を使用することを検討してください。
  3. 使用している行列の順序について考えてみてください。それは行優先ですか? または列の主要な?キャッシュ ミスは、そこで行っている他の何よりもコストがかかります。空間的な局所性と再利用を利用したい場合は、最も内側のループ (計算が行われる場所) がプリフェッチされた隣接する行列要素にアクセスするようにループを並べ替えます。
  4. アラインされたメモリ割り当てを行うと、ベクトル化がより簡単かつ効率的になります。
  5. ループの展開とブロックの使用を検討してください
于 2012-12-05T18:20:36.710 に答える