ホームページ > バックエンド開発 > C++ > Intel CPU で 32 ビット ループ カウンターを 64 ビットに置き換えると、「_mm_popcnt_u64」のパフォーマンスが低下するのはなぜですか?

Intel CPU で 32 ビット ループ カウンターを 64 ビットに置き換えると、「_mm_popcnt_u64」のパフォーマンスが低下するのはなぜですか?

Patricia Arquette
リリース: 2024-12-03 15:04:10
オリジナル
729 人が閲覧しました

Why Does Replacing a 32-bit Loop Counter with 64-bit Cause Performance Degradation with `_mm_popcnt_u64` on Intel CPUs?

32 ビットのループ カウンタを 64 ビットに置き換えると、Intel CPU の mm_popcnt_u64 で異常なパフォーマンスの偏差が発生します

概要

この記事では、32 ビット ループ カウンタを_mm_popcnt_u64 組み込み関数を使用した、パフォーマンスが重要なループ内の 64 ビット カウンター。この問題により、Intel CPU のパフォーマンスが大幅に低下し、実行速度の低下につながりました。著者は、この動作の背後にある理由を調査し、考えられる解決策を提供します。

詳細

問題のコードには、データの配列を反復処理してポップカウントを実行するループが含まれています。 x86 組み込み命令を使用した操作。ループ カウンター変数は最初は符号なし整数でしたが、これを 64 ビット符号なし整数 (uint64_t) に置き換えると、パフォーマンスが約 50% 低下しました。

原因を調査するために、作成者は次のようにコードをコンパイルしました。さまざまな最適化フラグを設定し、結果のアセンブリ コードを分析しました。彼らは、32 ビット バージョンと 64 ビット バージョンで異なるアセンブリが生成されることを観察し、コンパイラのバグを疑いました。

しかし、異なるコンパイラでコードをテストした後、作成者は問題はないと結論付けました。これはコンパイラのバグが原因ではなく、ハードウェアの誤ったデータ依存関係が原因です。 _mm_popcnt_u64 命令を Intel Sandy/Ivy Bridge および Haswell プロセッサで使用すると、宛先レジスタに対する誤った依存関係が示され、宛先の準備ができるまで命令は実行前に待機します。この誤った依存関係はループの繰り返し全体に引き継がれ、プロセッサが異なる反復を並列化できなくなり、パフォーマンスの低下につながる可能性があります。

著者は、popcount 操作を分離し、誤った依存関係を解消することでパフォーマンスの違いを実証するインライン アセンブリ テストを提示しています。鎖。これらのテストは、誤った依存関係がパフォーマンスに大きな影響を及ぼし、速度が 18.6195 GB/s から 8.49272 GB/s に低下することを示しています。

この記事では、この問題が Intel CPU に影響するのに対し、AMD プロセッサには影響することも強調しています。これは間違っていないようです

解決策

このパフォーマンスの問題を軽減するために、著者はいくつかの解決策を提案しています。

  • 代わりに 32 ビット ループ カウンターを使用します。この特定のループの 64 ビット カウンターの。
  • 64 ビット ループを使用する場合カウンタが必要な場合は、popcount 操作で使用する前に宛先レジスタを明示的にゼロにして、誤った依存関係の連鎖を断ち切ります。
  • この誤った依存関係を認識し、それを補うコードを生成するコンパイラを使用してください。

以上がIntel CPU で 32 ビット ループ カウンターを 64 ビットに置き換えると、「_mm_popcnt_u64」のパフォーマンスが低下するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート