3

WindowsでのクリティカルセクションとMutexのパフォーマンスを比較するための小さなプログラムを作成しました。

私が実行したテストでは、クリティカルセクションの取得が遅いようです:O両方の時間がほぼ同じ時間かかる理由と、内部で何が起こっているのかを誰かが説明できますか。

これは私が使用したタイマーです-http://cplus.about.com/od/howtodothingsi2/a/timing.htm

#include "stdafx.h"
#include<iostream>
#include<vector>
#include "h_timer.h"
#include<WinBase.h>
#include<Windows.h>
#include<stdio.h>

#define MAX_THREADS 2000  
//Comment and Uncomment this to enable/disable critialSection / Mutex
#define CRIT 1

using namespace std;

HANDLE Mutex;
CRITICAL_SECTION critSection;
DWORD WINAPI Contention( LPVOID );

int main( void )
{
    HANDLE Thread[MAX_THREADS];
    DWORD ThreadID;
    int i;

#ifdef CRIT
//create a critical section
InitializeCriticalSection(&critSection);
#else

    // Create a mutex with no initial owner
    Mutex = CreateMutex( NULL, FALSE,NULL);

#endif

    // Create worker threads

CStopWatch timer, tempTimer;
timer.startTimer();
    for( i=0; i < MAX_THREADS; i++ )
    {
        Thread[i] = CreateThread( NULL,
                     0,(LPTHREAD_START_ROUTINE)Contention,NULL,0,&ThreadID);
    }
    WaitForMultipleObjects(MAX_THREADS, Thread, TRUE, INFINITE);

    timer.stopTimer();
    cout<<endl<<"Elapsed Time:"<<timer.getElapsedTime();
    cin.get();
    // Close thread and mutex handles

    for( i=0; i < MAX_THREADS; i++ )
    CloseHandle(Thread[i]);

    CloseHandle(Mutex);
    return 0;
}


DWORD WINAPI Contention( LPVOID lpParam )
{
    #ifdef CRIT
EnterCriticalSection(&critSection);
//printf("ThreadId: %d\n",GetCurrentThreadId());
//printf("Let's try Again. %d\n\n", GetCurrentThreadId());
LeaveCriticalSection(&critSection);

#else
// lpParam not used in this example
    UNREFERENCED_PARAMETER(lpParam);
    DWORD dwCount=0, dwWaitResult;

    // Request ownership of mutex.
    dwWaitResult = WaitForSingleObject(
            ghMutex, // handle to mutex
            INFINITE); // no time-out interval
        dwCount++;
    ReleaseMutex(ghMutex);
#endif

return TRUE;
}

2000スレッドの場合、クアッドコアHPZ210では、どちらも約1.5秒かかります。

4

2 に答える 2

13

私は2つの要因があると思います:

主に-あなたのプログラムはスレッド作成のオーバーヘッドによって支配されています。2000スレッドを作成および破棄し、スレッドごとに1回だけミューテックス/CSにアクセスします。スレッドの作成に費やされた時間は、ロック/ロック解除時間の違いを圧倒します。

また、これらのロックが最適化されたユースケースをテストしていない可能性があります。それぞれがミューテックス/CSに何千回もアクセスしようとする2つのスレッドを生成してみてください。

于 2012-07-04T01:49:16.293 に答える
9

クリティカルセクションは、ユーザーモードとカーネルモードのハイブリッドです。彼らは、より高価なセマフォ(カーネルモード)にフォールバックする前に、スピンロック(ユーザーモード)を使用してスレッドがコンテキストスイッチしないようにしようとします。これにより、実際のシナリオでのパフォーマンスが向上します。対照的に、ミューテックスは純粋にカーネルモードであり、すぐに待機してコンテキストスイッチを実行します。

2000スレッド間で100%の競合を発生させることで、クリティカルセクションがほぼ確実に可能な限り回転し、CPUを消費してから、最終的にミューテックスが実行することを正確に実行し、カーネルモードで待機を実行するようになりました。したがって、この状況で速度を落とすのは理にかなっています。

そして、ジャプリスが言ったこと。スレッドの作成は非常に遅いです。

于 2012-07-04T01:57:30.707 に答える