編集:( 質問されている実際の質問から逸脱し、混乱を引き起こしているため、詳細を削除しています。OPは使用されていると想定しています。)restrict
restict
あなたの質問の変換は、最適化コンパイラにとって確かに些細なことですが、それはアクトンの論文が示唆していることではありません。
これが論文で行われた変換です:
このコード...
for (size_t i=0;i<count*stride;i+=stride)
{
velocity_x[i] += acceleration_x[i] * time_step;
velocity_y[i] += acceleration_y[i] * time_step;
velocity_z[i] += acceleration_z[i] * time_step;
position_x[i] += velocity_x[i] * time_step;
position_y[i] += velocity_y[i] * time_step;
position_z[i] += velocity_z[i] * time_step;
}
...このコードに変換されました:
for (size_t i=0;i<count*stride;i+=stride)
{
const float ax = acceleration_x[i];
const float ay = acceleration_y[i];
const float az = acceleration_z[i];
const float vx = velocity_x[i];
const float vy = velocity_y[i];
const float vz = velocity_z[i];
const float px = position_x[i];
const float py = position_y[i];
const float pz = position_z[i];
const float nvx = vx + ( ax * time_step );
const float nvy = vy + ( ay * time_step );
const float nvz = vz + ( az * time_step );
const float npx = px + ( vx * time_step );
const float npy = py + ( vy * time_step );
const float npz = pz + ( vz * time_step );
velocity_x[i] = nvx;
velocity_y[i] = nvy;
velocity_z[i] = nvz;
position_x[i] = npx;
position_y[i] = npy;
position_z[i] = npz;
}
最適化とは何ですか?
最適化は、提案されているように、1つの式を3つの式に分離することではありません。
最適化とは、特定のデータを操作する命令の間に有用な命令を挿入することです。
velocity_x[i]
に移動してvx
からnvx
戻ってデータを追跡する場合velocity_x[i]
、CPUはこれらの各ステップ間で他の作業を実行しています。
なぜこれが最適化なのですか?
最近のCPUは通常、パイプラインアーキテクチャを備えています。
命令は段階的に実行されるため、CPUでは複数の命令を同時に処理できます。ただし、命令が完全に実行されていない別の命令の結果を必要とする場合、このパイプラインは停止します。停止した命令を実行できるようになるまで、それ以上の命令は実行されません。
最適化コンパイラがこれを自動的に実行しないのはなぜですか?
ある人はそうします。
GCCは、この最適化では比較的貧弱であるとして際立っています。
上記の両方のループをgcc4.7(x86-64アーキテクチャ、-O3での最適化)を使用して分解しました。同様のアセンブリが作成されましたが、命令の順序が異なり、最初のバージョンでは、いくつかの命令の範囲内で単一のフロートがロード、変更、および保存される重要なストールが生成されました。
ここでgccの命令スケジューリングについて少し読むか、Webでgcc命令スケジューリングを検索して、この問題に関する多くの不満のある記事を確認してください。