2013-08-26 18 views
5

私はいくつかのコードをウィンドウに移植しており、スレッディングが非常に遅いことがわかりました。このタスクは、Windows(Xeon E5-2670 8コア2.6GHz = 16コア×2)とLinux(Xeon E5-1607 4コア3GHz)3.5秒で300秒かかる。 vs2012 expressを使用します。ウィンドウへのスレッドの移植。クリティカルセクションが非常に遅い

私は、すべてのEnterCriticalSection()を呼び出し、std :: stack、LeaveCriticalSectionの80バイトジョブをポップし、いくつかの作業(合計250kジョブ)を実行しています。

すべてのクリティカルセクションコールの前後に、スレッドIDと現在の時刻が表示されます。

  • シングルスレッドのロックの待機時間がある〜スタックから仕事をポップする160msで
  • は休暇を呼び出す〜3msの
  • を取る仕事は〜1msの
をとる〜3msの
  • を取ります

    (デバッグ/リリースではおおよそ同じですが、デバッグにはもう少し時間がかかります)コードを適切にプロファイルできるようにしたいと思います:P)

    コメントアウトジョブ・コールによりプロセス全体が2秒(Linuxよりもまだ)かかるようになります。

    私はqueryperformancecounterとtimeGetTimeの両方を試しましたが、どちらもおおよそ同じ結果を示しています。

    AFAIKこの仕事は決して同期呼び出しを行いませんが、そうでないと減速については説明できません。

    なぜスタックからコピーしてpopを呼び出すのが長すぎるのか分かりません。 もう一つの非常に混乱しているのは、なぜleave()の呼び出しに時間がかかるのかです。

    なぜそれがゆっくりと動いているのか推測できますか?

    プロセッサの違いが100倍のパフォーマンス差を与えるとは思えませんでしたが、デュアルCPUに関連している可能性はありますか? (内部コアとは別のCPU間で同期する必要があります)。

    ところで、私はstd :: threadを認識していますが、私のライブラリコードをpre C++ 11で動作させたいと思っています。

    編集削除のLinuxの#ifdefのものと

    //in a while(hasJobs) loop... 
    
    EVENT qwe1 = {"lock", timeGetTime(), id}; 
    events.push_back(qwe1); 
    
    scene->jobMutex.lock(); 
    
    EVENT qwe2 = {"getjob", timeGetTime(), id}; 
    events.push_back(qwe2); 
    
    hasJobs = !scene->jobs.empty(); 
    if (hasJobs) 
    { 
        job = scene->jobs.front(); 
        scene->jobs.pop(); 
    } 
    
    EVENT qwe3 = {"gotjob", timeGetTime(), id}; 
    events.push_back(qwe3); 
    
    scene->jobMutex.unlock(); 
    
    EVENT qwe4 = {"unlock", timeGetTime(), id}; 
    events.push_back(qwe4); 
    
    if (hasJobs) 
        scene->performJob(job); 
    

    とミューテックスクラス、...

    CRITICAL_SECTION mutex; 
    
    ... 
    
    Mutex::Mutex() 
    { 
        InitializeCriticalSection(&mutex); 
    } 
    Mutex::~Mutex() 
    { 
        DeleteCriticalSection(&mutex); 
    } 
    void Mutex::lock() 
    { 
        EnterCriticalSection(&mutex); 
    } 
    void Mutex::unlock() 
    { 
        LeaveCriticalSection(&mutex); 
    } 
    
  • +0

    Linuxで何を使用していましたか?クリティカルセクションでstd :: stackへのアクセスのみを保護していますか? – xanatos

    +2

    スレッドIDと現在時刻はどこに出力されますか? – avakar

    +0

    言語を選択してください。そして、これは奇妙に思える。 [SSCCE](http://www.sscce.org)が実用的であることは確かに簡単ですね。 Windowsでの私の経験は、比較的コンパイルされたLinuxディストリビューションに比べていくぶん控えめでしたが、これはかなり広い隙間に見えます。 – WhozCraig

    答えて

    0

    あなたの窓のスレッドがスーパーの競合に直面しているように思えます。彼らは完全に連載されているようです。クリティカルセクションと32スレッドで合計処理時間は約7msです。すべてのスレッドがロックにキューイングされている場合、キュー内の最後のスレッドは約217msのスリープ状態になるまで実行されません。これは、あなたの160msの待機時間からあまり離れていません。

    スレッドがクリティカルセクションに入る以外に何もする必要がない場合は、作業を行い、クリティカルセクションを離れると、これは私が期待する動作です。

    Linuxのプロファイリングの振る舞いを特徴づけ、プログラムの動作が本当にリンゴと比較しているかどうかを確認してください。

    +0

    私は同意します、彼らはゆるやかに順番に実行されているように見えます(時には実行順序に少しの違いがあります)。それらを直列化するコードはなく、80バイトのコピーとポップは私の仕事よりもずっと速くなければなりません。実際に意味をなさないのは、LeaveCriticalSectionを呼び出す時間です。シリアライゼーションはクリティカルセクションの根底にある問題の症状だと私は考えています。私は、Linux上での競合を二重チェックします。 – jozxyqk

    1

    ウィンドウのCRITICAL_SECTIONは、最初に入力したときにタイトなループで回転します。スピン・ループの実質的な期間が経過しない限り、EnterCriticalSectionを呼び出したスレッドは延期されません。したがって、同じクリティカルセクションで32スレッドを競合させると、多くのCPUサイクルが浪費され、無駄になります。代わりにミューテックスを試してみてください(CreateMutexを参照してください)。

    +3

    [私は同じと思う](http://stackoverflow.com/questions/18442574/porting-threads-to-windows-critical-sections-are-very-slow#comment27103010_18442574)、スピン数を調整することはできませんより適切な/より速いミューテックスを使用するよりも? – dyp

    関連する問題