2013-03-19 1 views
0

지금은 다중 스레드 동기화를 실험하고 있습니다. backround의 경우 약 100,000 개의 객체 집합이 있습니다. 아마도 더 많은 것입니다. 초당 여러 번 다른 방식으로 처리하려고합니다.이벤트를 통한 스레드 동기화의 오버 헤드

이제 나와 관련된 것은 동기화의 성능입니다.

이것이 제대로 작동해야한다고 생각합니다 (모든 보안 측면이 생략되었으므로 테스트 프로그램 일 뿐이며 오류가 발생하면 프로그램이 중단됩니다 ..). 나는 두 개의 펑션을 썼다. 첫 번째는 프로그램의 주 스레드에 의해 실행되었고 두 번째는 모든 추가 스레드에 의해 실행되었다. 8 개 논리적 코어 12500 개체 각, 현대 멀티 코어 프로세서의 8 개 부분 집합으로 분할, 우리는 위에서 100000 개 객체를 가지고 말 :

void SharedWorker::Start() 
{ 
    while (bRunning) 
    { 
     // Send the command to start task1 
     SetEvent(hTask1Event); 

     // Do task1 (on a subset of all objects) here 

     // Wait for all workers to finish task1 
     WaitForMultipleObjects(<NumberOfWorkers>, <ListOfTask1WorkerEvents>, TRUE, INFINITE); 

     // Reset the command for task1 
     ResetEvent(hTask1Event); 

     // Send the command to start task2 
     SetEvent(hTask2Event); 

     // Do task2 (on a subset of all objects) here 

     // Wait for all workers to finish task2 
     WaitForMultipleObjects(<NumberOfWorkers>, <ListOfTask2WorkerEvents>, TRUE, INFINITE); 

     // Reset the command for task2 
     ResetEvent(hTask2Event); 

     // Send the command to do cleanup 
     SetEvent(hCleanupEvent); 

     // Do some (on a subset of all objects) cleanup 

     // Wait for all workers to finish cleanup 
     WaitForMultipleObjects(<NumberOfWorkers>, <ListOfCleanupWorkerEvents>, TRUE, INFINITE); 

     // Reset the command for cleanup 
     ResetEvent(hCleanupEvent); 
    } 
} 

DWORD WINAPI WorkerThreads(LPVOID lpParameter) 
{ 
    while (bRunning) 
    { 
     WaitForSingleObject(hTask1Event, INFINITE); 

     // Unset finished cleanup 
     ResetEvent(hCleanedUp); 

     // Do task1 (on a subset of all objects) here 

     // Signal finished task1 
     SetEvent(hTask1); 

     WaitForSingleObject(hTask2Event, INFINITE); 

     // Reset task1 event 
     ResetEvent(hTask1); 

     // Do task2 (on a subset of all objects) here 

     // Signal finished task2 
     SetEvent(hTask2); 

     WaitForSingleObject(hCleanupEvent, INFINITE); 

     // Reset update event 
     ResetEvent(hTask2); 

     // Do cleanup (on a subset of all objects) here 

     // Signal finished cleanup 
     SetEvent(hCleanedUp); 
    } 

    return 0; 
} 

난 그냥 당신에게 약간의 예를 들어 줄거야, 내 요구 사항을 지적하려면 . 관련 부분은 시간입니다. 모든 작업은 약 8ms 이내에 수행되어야합니다.

지금 내 질문이 있습니다. 분할 처리로 시간이 크게 늘리거나 너무 비싼 이벤트를 통한 동기화가 가능합니까? 또는 모든 작업을 이런 방식으로 수행해야하는 경우 스레드를 적은 노력 또는 프로세스 시간으로 동기화하는 다른 방법이 있습니까?

+1

그것은 당신의 작업에 대한 자세한 내용을 모르고 대답하는 것은 불가능하고, 자신의 자원 요구 사항 (CPU, I/O) :

그래서 의사 코드는 다음과 같다 할 수 있습니다. 일반적으로 대기 상태에서 스레드가 소비 한 시간을 최소화해야합니다. 비동기 처리는 스레드 간 신호 전달의 한 가지 대안이지만 작업 실행에는 불가능할 수도 있습니다. –

+0

아, 죄송합니다. 리소스 요구 사항을 완전히 잊어 버렸습니다. 작업 1과 2는 순수한 CPU이며, 정리 2는 작업 2의 개체를 지연 삭제할 때만 사용됩니다. 비동기 처리는 task1, task2 및 정리가 순서를 유지해야하는 고정 된 순서이므로 불행히도 대안이 아닙니다. 다음 작업을 완료해야합니다. 하나 시작할 수 있습니다. – rootmenu

+0

자신의 스레딩/시그널링을 사용하는 대신 OpenMP와 같은 것을 사용할 수있는 것 같습니다. 비슷한 순서의 작업을 병렬로 실행하는 데 적합합니다. http://msdn.microsoft.com/en-us/library/tt15eb9t(v=vs.110).aspx –

답변

0

단일 개체에 대한 처리 속도가 빠르면 스레드간에 분할하지 마십시오. 윈도우에서의 스레드 동기화는 모든 컨텍스트 스위치에서 50 밀리 초를 잘 먹을 것입니다. 이 시간은 시스템에 의해 사용되는 것이 아니라 시스템에서 다른 것이 실행되고있는 시간입니다.

그러나 모든 개체 처리에 약 8ms가 걸리면 스레드 풀 전체에서 작업을 예약 할 수 있습니다. 그러나 객체 처리는 약간 다를 수 있으며 큰 수의 작업자 스레드는 다른 순간에 작업을 완료합니다.

더 나은 접근 방법은 처리 할 개체를 추가하고 처리 할 개체를 추가하는 동기화 된 개체 대기열을 구성하는 것입니다. 또한 스레드의 일정 간격보다 훨씬 적은 단일 개체의 처리로 처리 스레드를 배치 (10-20 등)로 가져 오는 것이 좋습니다. 풀에서 최적의 작업자 스레드 수와 테스트를 통해 최적의 배치 크기를 예측할 수 있습니다.

main_thread: 
    init queue 
    start workers 

    set counter to 100000 
    add 100000 objects to queue 
    while (counter) wait(); 

worker_thread: 
    while (!done) 
     get up to 10 objects from queue 
     process objects 
     counter -= processed count 
     if (counter == 0) notify done 
+1

Windows에서 컨텍스트 스위칭이 50ms가 걸린다는 진술에 대한 타당성을 제시하십시오. –

+0

스레드 풀은 내가 원하는 것과 다른 목적을 가지고 있습니다. 내 루프는 계속 실행되고 중지 될 때까지 동일한 세 가지 작업을 계속 반복합니다. 이 세트는 주로 동일하게 유지되며 (반복 당 10 개 미만의 새/삭제 된 객체) 동기화 된 대기열은 큰 오버 헤드가됩니다. 또한 루프의 반복은 단일 객체의 처리가 아니라 8ms가 걸릴 수 있습니다. – rootmenu

+0

@SteveTownsend 정확한 인물이 없지만 링크는 다음과 같습니다. http://stackoverflow.com/questions/2898344/how-long-does-it-take-each-thread-timeslice-in-windows- xp. 내 경험에 의하면 스레드는 문맥 전환 (질문 주석과 같이)에서 50 밀리 초보다 상당히 느슨해 질 수 있습니다. –