2009-11-29 8 views
6

現在、私はC++コードを書いており、自分のコードに多くのメモリバリア/フェンスを使用しています。私はMBがコンパイラとハードウェアに書き出し/書き戻しの順序を変更しないように指示していたことは知っています。しかし、私は実行時にこの操作がプロセッサにとってどれほど複雑であるか分かりません。メモリバリア/フェンスのオーバーヘッド

私の質問です:そのような障壁のランタイムオーバーヘッドは何ですか?私はグーグルで有用な答えを見つけられませんでした... オーバーヘッドは無視できますか?あるいは、重大なMBの使用を重大なパフォーマンス上の問題につなぎますか?

よろしくお願いいたします。

答えて

2

指示が何をするかを考えてみてください。 CPUがロジックに関して複雑なことをするわけではありませんが、すべての読み取りと書き込みがメインメモリにコミットされるまで強制的に待機します。したがって、コストは実際にメインメモリにアクセスするコスト(および未処理の読み取り/書き込みの数)に依存します。

メインメモリへのアクセスは一般的にかなり高価です(10〜200クロックサイクル)が、ある意味ではバリアがなくても済むでしょう。他の命令を同時に実行することで隠すことができますコストをあまり感じていませんでした。

CPUの(コンパイラの)命令の再スケジューリング機能も制限されているため、隣接する命令をインターリーブできないために間接的なコストがかかる可能性があります。

+3

この回答は正しくありません。 「すべての読み取りと書き込みがメインメモリにコミットされました」という文は間違っています。メインメモリはメモリフェンスの影響を受けません。少なくとも、キャッシュの一貫性を保ちながら、なぜメインメモリに向かうのでしょうか?また、メインメモリアクセスのサイクルタイムはオフになっています。 – Timoteo

1

算術的および「通常の」命令と比較して、これらは非常に高価であると理解していますが、その命令をバックアップする番号はありません。私は指示の効果を説明することによってjalfの答えが好きで、少し追加したいと思います。

障壁にはいくつかの種類がありますので、その違いを理解することが役に立ちます。 Jalfのような障壁は、ロックワードをクリアする前にミューテックスの実装で必要となります(ppcではlwsync、ia64ではst4.relなど)。すべての読み込みと書き込みが完了していなければならず、メモリアクセスを持たず、進行中のメモリ操作に依存しないパイプラインの後の命令だけを実行することができます。

もう1つのタイプの障壁は、ロックを取得するときにmutex実装で使用するソートです(例:ppcのisyncまたはia64のinstr.acq)。これは将来の命令に影響を及ぼします。したがって、依存しないロードがプリフェッチされた場合は、それを破棄する必要があります。例:低迷ビットのチェックのチェックが完了する前にsomethingElseはレジスタにそれを作った場合、取得バリア(借入IA64の専門用語)なし

 
if (pSharedMem->atomic.bit_is_set()) // use a bit to flag that somethingElse is "ready" 
{ 
    foo(pSharedMem->somethingElse) ; 
} 

、あなたのプログラムは、予期しない結果を有することができます。

バリアの第3のタイプがあり、一般的にはあまり使用されず、ストアのロード順序を強制する必要があります。このような順序付け強制命令の命令の例は、ppc(ヘビーウエイト同期)、ia64上のMF、sparc上のmembar #storeload(TSOでも必要です)などです。例示する擬似コードなどIA64を使用

は、一つのロードがストアに従うことはguarenteeを有しないものとの間でのMFなし

 
st4.rel 
ld4.acq 

を有していたと仮定する。 st4.relの前にあるロードとストアは、そのストアまたは "後続の"ロードの前に実行されますが、そのロードや他の将来のロード(おそらく非依存の場合はストアします)が侵入する可能性があることを知っています。さもないと。

mutexの実装では、実装では取得と解放の障壁だけが使用される可能性が高いため、「クリティカルセクション」の間にロック解除後のメモリアクセスが実際に発生することがあります。

関連する問題