4

ループの展開 (C/C++ で) が最適化に役立つのはどの時点かを最初に説明してもらえますか?

2 番目に、最初の質問に関連して、展開をそれ以上実行してはいけないのはどの時点ですか? アンローリングは、操作を 2 の累乗のバッチに分割して常に実行する必要がありますか? それとも、CPU が実行できる計算の数に関係していますか? キャッシュ ライン サイズの乗数である比率は? 等

たとえば、0 から 99 までの for ループがあった場合、どちらが良いか (試行錯誤以外に) どのように決定するか - 科学的な方法はありますか?

  • 0 ~ 49 および 1 ループあたり 2 つの「操作」
  • ループごとに 0 ~ 24 および 4 つの「操作」
  • ループごとに 0 ~ 19 および 5 つの「操作」
  • ループごとに 0 ~ 9 および 10 の「操作」
4

1 に答える 1

6

Duff の Deviceについて言及せずに、ループのアンローリングに関する質問をこれほど長い間答えないままにしておくことはできません。この実装は従来のバージョンとは少し異なりますが、それでも機能します。

メモリ ブロックにマスクを適用するとします。

while (n-- > 0) {
    *ptr++ &= mask;
}

次に、これは次のように展開できます。

switch (n % 4) do {
case 0: *ptr++ &= mask;
case 3: *ptr++ &= mask;
case 2: *ptr++ &= mask;
case 1: *ptr++ &= mask;
} while ((n -= 4) > 0);

ループ展開は、反復ジャンプのコストがループ反復内で実行される作業のコストのかなりの割合である場合に役立ちます。優れた最適化コンパイラは、十分な最適化レベルでそれを把握できます。コンパイラが失敗した場合にのみ、自分で展開する必要があります。

コメントで述べたように、ジャンプの計算コストが展開されたループ本体の計算と比較して重要でなくなったら、展開する必要はありません。ループのアンロールを極端に行うと、命令キャッシュのスラッシュが発生し、パフォーマンスが低下する可能性があります (関数のインライン展開を過度に積極的に使用するのと同様)。

于 2013-06-22T01:05:51.263 に答える