コンパイラーは、配列への交互アクセスを検出してメモリーにインターリーブできますか?


7

配列が別の方法でアクセスされるループを最適化するコンパイラを設計することは可能ですか?たとえば、次のようになります。

// int[] a,b
int sum = 0;
for(int i = 0; i < n; i++)
{
  sum += a[i] + b[i];
}

通常のシーケンシャルアレイ装置と、a[i]及びb[i]互いに離れメモリであってもよいです。したがって、優れたコンパイラ最適化はそれを検出しa[i]b[i]常に「同時に」アクセスされることを検出し、インターリーブされた配列を格納します。a[0] b[0] a[1] b[1] ...つまり、1つのメモリアクセスでa[i]との両方を取得できますb[i]


ようこそ!私はあなたの質問を明確にしようとしました。切断していないか確認してください。その内容については、コンパイラーが単純なケースを検出できると確信していますが、一般的に、その単一の方法でのみ使用される多くの配列があるとは思いません。また、この方法で配列を格納することは、RAM上で時間的に効率が悪くなるはずです。Daveの参考文献が示唆しているように、他の効果がプレイされている可能性があります。
ラファエル

ここでの根本的な仮定が最新のキャッシングアーキテクチャに当てはまるかどうかはわかりません。キャッシュが両方のアレイのかなりの部分に対応できる十分な大きさである限り(そしてもちろん、他のプロセスによって競合されていない限り)、単純なレイアウトへのアクセスは効率的です。
dmckee ---元モデレーターの子猫2012

@Raphael:あなたの編集により、質問に予期しない要件が追加されたと思います。私は、それはそれを必要とは思わないa[i]し、b[i]一つのメモリ操作で取得することが、彼らは近くの優れたキャッシュ・パフォーマンスのためにメモリに配置されたこと。
Dave Clarke

@DaveClarke実際に質問の1つの側面では、1つのメモリ操作でaとbの対応する値を取得することを意味していました。
krammer 2012

1
確認する参照を見つけることができません。Sunは、約10〜15年前に仕様のベンチマーク179.artと171.swimを「破り」ました(つまり、最適化により、ハードウェアが保証するよりも優れた数値が得られました)。ISTRは、関連する最適化を伴うものでした。
AProgrammer 2012

回答:


11

説明に一致するいくつかの作業が行われました。例えば:

  • マルチバンクメモリのエネルギーを削減するためのコンパイラー指向アレイインターリービング。Delaluz、V. 2002による設計自動化会議。ASP-DAC2002の議事録。第7回アジアおよび南太平洋およびVLSI設計に関する第15回国際会議。議事録。

このような最適化について説明します。


ありがとう。ベクトル化されたループを利用するアーキテクチャで同じ方法はありますか?
krammer 2012

OPの例では、そのような最適化を行うコンパイラーは、SIMDをサポートするためにブロッキングを使用する場合もあります。一部のハードウェアプリフェッチャーはページ境界を超えないため、このような変換は最適化ではない可能性があります。これはメモリ構成とも相互作用し、DRAMバンクの競合を回避したり(バンクの競合により帯域幅が減少したり、エネルギー使用量が増加したり)、複数のメモリチャネルが利用されない可能性があります。
Paul A. Clayton、

1

この場合の短い答えは、通常、メモリレベルの並列処理は、このようなループで複数の個別のメモリブロックをカバーするのに十分であるということです。単一のストリームにインターリーブすると、実際にはプロセスが遅くなります。多くのキャッシュおよび外部メモリアルゴリズムは、このようなある程度の並列処理を想定しています。

より長く、より理論的な答えは、キャッシングはプログラム実行の多くの側面のようなものであり、簡単に見えますが、一般的に予測するのは難しいことが証明されています。たとえば、キャッシュブロックは、特定のプロセスが停止した場合にのみフェッチする必要があるかもしれません。それを予測できるコンパイラは控えめに言っても面白いでしょう。

既知のアクセスシーケンスを最適化する(それらを予測する必要がない)より単純なケースは、それ自体NP困難です。

特に、メモリアクセスのシーケンスが与えられ、このシーケンスのキャッシュミスの数を最小限に抑えるために、データをメモリに配置する必要があるとします。P≠NPの場合、非常に自由度の高い近似比まで最適解を効率的に近似できないことを示します。

PetrankとRawitz、キャッシュを意識したデータ配置の難しさ


-1

あなたの例は完全ではなく、配列はどこにも宣言されておらず、どこにも初期化されていません。

一般的なプログラミングコンテキストでは、この種の最適化は「価値があるよりも厄介なこと」になると思います。ほとんどの配列は複数の場所からアクセスされるため、コンパイラは多くの場合、どの場所が最も重要であるかを推測する必要があります。また、多くの配列はコンパイル単位の境界を関数へのパラメーターまたはグローバル変数として渡すため、この方法で変更することはできません。最後に、デバッグ情報がより複雑になります。


広告パラグラフ1:このサイトはプログラミングではなくコンピュータサイエンスを扱っています。広告段落2:特定の例を挙げたり、参照を引用したりできますか?
ラファエル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.