2

特定のアプリケーションでは、個々のインデックス情報を保持しながら、ネストされたループを 1 つに折りたたむ必要があります。

for j in N:
  for i in M:
    ... A(i,j) ...

// Collapse the loops
for ij in MN:
  ... A(i,j) ...

そのため、除算/モジュロ (高価な操作) を使用して ij から i,j を回復する明白な方法と、if ステートメントを使用する (ベクトル化、分岐予測の問題を破る) を調べました。 ):

j += (i == m)
i *= (i != m)
++i, ++ij

おそらくそれを行うためのさらに良い方法はありますか?ありがとう

4

3 に答える 3

8

一般に、説明したようにループを折りたたんでも、パフォーマンス上の利点はありません。

コンパイラはそのようなループを折りたたむことがありますが、通常は予期しない方法で行われます。

特定の言語または特定のプラットフォームでは、一般的に次の方法でループを高速化できます。

  • カウントダウン
  • 本体で呼び出される関数を「インライン」にするか、別の関数ではなくループ本体にコードを含める
  • 通常はコマンドラインオプションを介してコンパイラを構成し、ループを「展開」してフレームポインタなどを削除します

しかし、どのような場合でも、そのような努力が保証されていることを確認するには、コードをプロファイリングする必要があります。

一般的に、私の経験では、このようなネストされたループは次の要素によって支配されます。

  1. コンテナ; 可能であればボクシングと境界チェックを避け、安全であることを知っている
  2. それらの他のメソッドを呼び出すコスト。利用可能な場合は「インライン」を使用してください
  3. 参照の局所性が悪いことによるパイプラインの失速。可能であれば記憶を整理する
  4. パイプラインは 2 番目の条件でストールします。if と間接参照が少ないほど良い

しかし、それは問題のドメインとプラットフォームに適用できるアドバイスではないかもしれません。 プロフィール

于 2010-01-22T06:51:15.763 に答える
0

他の方法で行った方が安いかもしれません。

for j in N:
  for i in M:
    ij=j*i+j
于 2010-01-22T06:45:10.623 に答える