2

次の for ループがあります。型配列をオンにすると、コードはベクトル化されません。タイプを '1' に固定すると、gcc はプリミタイズ ベクトル化を実行します。ある種のベクトル化をトリガーするための推奨事項はありますか?

#define type(M,N) type[(M)*sizeX + (N)]
for (int i = 0; i < sizeY - 1; i++)
{
    for (int j = 0; j < sizeX - 1; j++)
    {
       const int id = type(i, j);
       //const int id = 1; //vectorizes
       const float A = this->A[id];
       const float B = this->B[id];
       a(i, j) = A * a(i, j) + B * (b(i, j) - b(i + 1, j))*(p[i]);
    }
 }

gcc 4.7.1 からのおおよその誤差

45: not vectorized: not suitable for gather A_26 = *D.14145_25;

編集 1

すべての配列はポインターとして格納され、restrictキーワードを使用して何らかのクラスのメンバーとして定義されます。

編集 2

type「 」が小さい場合、何かできることはありますか?

編集 3

小さいとは 8 を意味します。

4

1 に答える 1

4

違いはメモリアクセスです。

の場合id = 1、次の配列の読み込みは単一の要素ベクトル ブロードキャストになります。

 const float A = this->A[id];
 const float B = this->B[id];

ただし、 の場合id = type[(i)*sizeX + (k)]、メモリ アクセスはストライドされます (連続していません)。

SSE および AVX でのベクターのロードとストアは、以下でのみ実行できます。

  1. 連続したメモリ ブロック。
  2. または、ベクトル全体にブロードキャストされる単一の要素から。

メモリのさまざまな部分から各ベクトル要素をロードするストライド メモリ アクセスを処理できません。

AVX2 は、このような「ギャザー/スキャッター」命令をサポートします。


編集に対処するには:

iintype(i, j)が 0 以外の場合、メモリ アクセスは引き続きストライドされます。そのため、ベクトル化は困難です。(効率は低下しますが、コンパイル時に決定される非常に小さなストライドが可能であるため、「不可能」ではなく「難しい」と言います。)

ここでの中心的な問題は、行列の行を反復処理していることです。これは、ギャザー/スキャッターのサポートなしではベクトル化できないだけでなく、キャッシュにも悪影響を及ぼします。

達成しようとしているタスクはわかりませんが、最大のパフォーマンスを得るには、別のデータ レイアウトを検討する必要があるかもしれません。

于 2012-10-30T10:16:36.203 に答える