実行が遅いプログラムにおけるメモリ管理のジレンマ
プログラムが特定の数の要素、特に 8192 を反復処理すると、顕著な減速。この現象は、メモリ管理に起因しており、さらなる調査が必要な複雑なトピックです。
コードの概要
問題のループを考えてみましょう。事前定義された行列に対して演算を実行します。
for (i = 1; i < SIZE - 1; i++) { for (j = 1; j < SIZE - 1; j++) { res[j][i] = 0; for (k = -1; k < 2; k++) for (l = -1; l < 2; l++) res[j][i] += img[j + l][i + k]; res[j][i] /= 9; } }
プログラムのパフォーマンスの不一致は、採用されているメモリ レイアウトの種類によって発生します。配列にアクセスする場合、最新のプロセッサは効率を最適化するために連続したメモリ ブロックを優先します。ただし、提供されたコードの場合のように、ループが要素を非線形に反復する場合、プロセッサは非順次データにアクセスしようとしてメモリ ストールが発生する可能性があります。
Super-アライメントとキャッシュの問題
問題の核心は、プロセッサがメモリ ブロックに優先的にアクセスする現象である「スーパー アライメント」にあります。これは特定のサイズ (多くの場合 16 バイトまたは 32 バイト) の倍数です。この場合、外側のループは行を反復し、内側のループは列を反復します。 SIZE が 2048 の倍数の場合、外側のループは行間でメモリの大部分をスキップし、プロセッサがデータを待機している間に遅延が発生します。
パフォーマンスの比較
次の実行時間はパフォーマンスを示しています。影響:
SIZE = 8191: 3.44 secs SIZE = 8192: 7.20 secs SIZE = 8193: 3.18 secs
解決策: ループの並べ替え
この問題の解決策は、外側のループが行ではなく列を反復するようにループを再配置することです。これにより、プログラムが連続したメモリ ブロックにアクセスするようになり、速度低下の原因となる非順次アクセスが排除されます。
変更されたループ:
for (j = 1; j < SIZE - 1; j++) { for (i = 1; i < SIZE - 1; i++) { ... (same operations as before) ... } }
この変更を実装すると、パフォーマンスの差異がなくなり、次の実行時間に見られるように:
SIZE = 8191: 0.376 seconds SIZE = 8192: 0.357 seconds SIZE = 8193: 0.351 seconds
以上が8192 要素を処理すると、メモリ アクセス パターンが原因でプログラムの速度が大幅に低下するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。