대기중인 스레드가있는 스레드 풀이 Windows 응용 프로그램의 큐에 푸시 될 때까지 대기합니다.C++ : 스레드 풀 및 컨텍스트 전환 속도 저하
1000 개의 작업을 순차적으로 풀의 대기열에 1000 개의 작업을 추가하는 기본 응용 프로그램 스레드에 루프가 있습니다 (작업을 추가 한 다음 작업이 완료 될 때까지 대기 한 후 다른 작업 x1000을 추가 함). 실제 병렬 처리는 발생하지 않습니다 그래서 ... 여기에 몇 가지 의사 코드입니다 :
////threadpool:
class ThreadPool
{
....
std::condition_variable job_cv;
std::condition_variable finished_cv;
std::mutex job_mutex;
std::queue<std::function <void(void)>> job_queue;
void addJob(std::function <void(void)> jobfn)
{
std::unique_lock <std::mutex> lock(job_mutex);
job_queue.emplace(std::move(jobfn));
job_cv.notify_one();
}
void waitForJobToFinish()
{
std::unique_lock<std::mutex> lock(job_mutex);
finished_cv.wait(lock, [this]() {return job_queue.empty(); });
}
....
void threadFunction() //called by each thread when it's first started
{
std::function <void(void)> job;
while (true)
{
std::unique_lock <std::mutex> latch(job_mutex);
job_cv.wait(latch, [this](){return !job_queue.empty();});
{
job = std::move(job_queue.front());
job_queue.pop();
latch.unlock();
job();
latch.lock();
finished_cv.notify_one();
}
}
}
}
...
////main application:
void jobfn()
{
//do some lightweight calculation
}
void main()
{
//test 1000 calls to the lightweight jobfn from the thread pool
for (int q = 0; q < 1000; q++)
{
threadPool->addJob(&jobfn);
threadPool->waitForJobToFinish();
}
}
그래서 기본적으로 작업이 큐와 메인 루프에 추가됩니다 무슨 일이 일어나고 있는지 기다려야하기 시작
기다리는 쓰레드는 그것을 집어 내고, 쓰레드가 끝나면 애플리케이션은 메인 루프가 계속되고 또 다른 작업이 큐에 추가 될 수 있음을 알린다. 그런 식으로 1000 개의 작업이 순차적으로 처리된다.
작업 자체는 작고 몇 밀리 초 만에 완료 할 수 있습니다.
그러나, 나는 뭔가 이상한 ....
가 완료 될 때까지 루프 걸리는 시간은 기본적으로 n은 스레드 풀의 스레드 수입니다 O (N)입니다 나타났습니다. 따라서 모든 시나리오에서 작업이 한 번에 하나씩 처리 되더라도 10 스레드 풀은 1 스레드 풀보다 전체 1000 작업을 완료하는 데 10 배 더 오래 걸립니다.
이유를 알아 내려고하고 있습니다. 내 유일한 추측은 컨텍스트 스위칭이 병목 현상 ... 어쩌면 덜 (또는 0일까요?) 컨텍스트 스위칭 오버 헤드는 오직 하나의 스레드가 잡을 때 필요합니다. 그러나 10 개의 스레드가 한 번에 하나의 작업을 처리하기 위해 계속해서 돌고있을 때 추가 처리가 필요합니까? 하지만 그건 나에게 의미가 없다 ... 스레드 B, C, D처럼 스레드 A의 작업을 잠금 해제하는 데 필요한 동일한 작업이 아닌가? 거기에 어떤 스레드가 다른 스레드가 주어질 때까지 상황을 잃지 않는 OS 레벨 캐싱이 있습니까? 따라서 동일한 스레드를 반복해서 호출하면 스레드 A, B, C를 순차적으로 호출하는 것보다 빠릅니까?
하지만이 시점에서 완전히 추측 할 수 있습니다. 어쩌면 다른 사람들이 왜 이러한 결과를 얻는 지에 대한 통찰력을 얻을 수 있습니다. 직관적으로 나는 단 한 번에 하나의 스레드 만 실행되는 동안 임의로 많은 수의 스레드를 가진 스레드 풀을 가질 수 있으며 [x] 작업의 총 작업 완료 시간은 동일합니다 (각 작업이 동일하고 총 작업 수가 동일하면 ...) 이유는 무엇입니까 그게 잘못된거야?
이것은 관련이 없지만 몇 개의 코어가 있습니까? – merlin2011
@ merlin2011 16 (2 CPU x 8 코어). – Tyson
또한 어떻게 벤치마킹합니까? 즉, 시작과 끝에서 시간을 측정하거나 각 작업에 대한 데이터를 수집하여 천천히 매 10 초마다 1이되는지 여부를 알 수 있습니까? – merlin2011