2016-09-18 24 views
1

のは、このような単純なifを想定してみましょうマルチスレッド:分岐予測と

if (something) 
    // do_something 
else 
    // do_else 

このif-else文が異なるスレッドで並列に実行され、各スレッドが異なる結果をもたらすが、自身の人生を通して一定であると仮定します。たとえば、スレッド1では、条件は常にスレッド2ではtrue、スレッド2ではtrueと評価されます。スレッド3では常に真であり、以下同様である。

分岐予測は、各スレッドの実行コンテキストが統計を作成すると見なしますか?なぜなら、そうは思わないが、テストで確認するのが難しいと思うから、CPUは条件がランダムなパターンに従うのを見て、全く予測しないからだ。

+1

スレッドを定義します。 CPUは明らかにOSスレッドを知らない。しかし、最近のほとんどのCPUは、ハードウェアスレッドについて知っています。 –

+1

分岐予測は、ナノ秒の分解能で動作するプロセッサー実装の詳細です。スレッドの実行は、ミリ秒の分解能で動作します。これらの6桁の差異は問題を無関係にします。 –

答えて

1

SMT(f.ex.ハイパースレッディング)を無視すると、ほとんどのアーキテクチャはハードウェアスレッドごとに分岐予測子を持ちます。 個々のコアのフェッチユニットと密接に結合されています。いくつかの(AMD?)は、L1/L2 Iキャッシュにいくつかの分岐予測情報を格納しますが、主に次のフェッチのためにターゲットにします。

SMTでコードを実行していない場合、あなたは天国におり、毎回100%の予測が得られます。

SMTでコードを実行すると、あなたの人生は地獄であり、50 +%の誤予測であることがよくあります。

問題を簡単に解決するには、より多くのコードを使用し、以前の条件を確認して、do_somethingまたはdo_elseを使用してコードのブランチを呼び出す必要があります。

あなたがあなたの枝を持っているあなたの関数を呼び出すループを持っている場合はあなたのような何かを行うことができます。(何か) do_something_loop()場合

。 else do_else_loop();

void do_something_loop(){ for(auto x:myVec) do_something; }

これは、2つのほぼ等しいコードブランチを維持する必要があるという欠点があります。

また、関数branch_me()を使ってテンプレート関数を作成することもできます。また、デッドコードを除去するという魔法のために、ループ内にブランチを作成するべきではありません。

C++コンセプトコード。

template<bool b_something> 
void brancher() { 
    // do things 
    if (b_something) 
    // do_something 
    else 
    // do_else 
    } 
    // do more things 
} 

void branch_user() { 
    if (something) { 
    for (auto x : myVec) 
     brancher<true>(); 
    } else { 
    for (auto x : myVec) 
     brancher<false>(); 
    } 
} 

これで、うまく機能しない外側機能の2つの分岐を維持するだけで済みます。