Tôi có một nhóm nhóm tùy chỉnh, tạo ra một số chủ đề mà mỗi chủ đề chờ đợi trên sự kiện (tín hiệu) của riêng họ. Khi một công việc mới được thêm vào nhóm luồng, nó sẽ đánh thức luồng miễn phí đầu tiên để nó thực hiện công việc.Chi phí đầu vào do sử dụng Sự kiện
Vấn đề là như sau: Tôi có khoảng 1000 vòng của mỗi khoảng 10'000 lần lặp lại làm. Các vòng lặp này phải được thực thi tuần tự, nhưng tôi có sẵn 4 CPU. Những gì tôi cố gắng làm là để chia các vòng lặp lặp lại 10'000 thành vòng lặp lặp lại 2'500 vòng, tức là một cho mỗi chủ đề. Nhưng tôi phải chờ 4 vòng nhỏ để hoàn thành trước khi chuyển sang lần lặp "lớn" tiếp theo. Điều này có nghĩa là tôi không thể bó các công việc.
Vấn đề của tôi là sử dụng nhóm luồng và 4 luồng chậm hơn nhiều so với thực hiện công việc tuần tự (có một vòng lặp được thực hiện bởi một chuỗi riêng biệt chậm hơn nhiều so với thực hiện trực tiếp trong chuỗi chính tuần tự).
Tôi đang sử dụng Windows, vì vậy tôi tạo sự kiện với CreateEvent()
và sau đó đợi một trong số chúng bằng cách sử dụng WaitForMultipleObjects(2, handles, false, INFINITE)
cho đến khi chủ đề chính gọi SetEvent()
.
Dường như toàn bộ sự kiện này (cùng với việc đồng bộ hóa giữa các chủ đề bằng các phần quan trọng) là khá đắt!
Câu hỏi của tôi là: việc sử dụng các sự kiện có "nhiều thời gian" là bình thường không? Nếu vậy, có cơ chế nào khác mà tôi có thể sử dụng và điều đó sẽ tốn ít thời gian hơn không?
Dưới đây là một số mã để minh họa (một số bộ phận có liên quan sao chép từ lớp hồ bơi thread của tôi):
// thread function
unsigned __stdcall ThreadPool::threadFunction(void* params) {
// some housekeeping
HANDLE signals[2];
signals[0] = waitSignal;
signals[1] = endSignal;
do {
// wait for one of the signals
waitResult = WaitForMultipleObjects(2, signals, false, INFINITE);
// try to get the next job parameters;
if (tp->getNextJob(threadId, data)) {
// execute job
void* output = jobFunc(data.params);
// tell thread pool that we're done and collect output
tp->collectOutput(data.ID, output);
}
tp->threadDone(threadId);
}
while (waitResult - WAIT_OBJECT_0 == 0);
// if we reach this point, endSignal was sent, so we are done !
return 0;
}
// create all threads
for (int i = 0; i < nbThreads; ++i) {
threadData data;
unsigned int threadId = 0;
char eventName[20];
sprintf_s(eventName, 20, "WaitSignal_%d", i);
data.handle = (HANDLE) _beginthreadex(NULL, 0, ThreadPool::threadFunction,
this, CREATE_SUSPENDED, &threadId);
data.threadId = threadId;
data.busy = false;
data.waitSignal = CreateEvent(NULL, true, false, eventName);
this->threads[threadId] = data;
// start thread
ResumeThread(data.handle);
}
// add job
void ThreadPool::addJob(int jobId, void* params) {
// housekeeping
EnterCriticalSection(&(this->mutex));
// first, insert parameters in the list
this->jobs.push_back(job);
// then, find the first free thread and wake it
for (it = this->threads.begin(); it != this->threads.end(); ++it) {
thread = (threadData) it->second;
if (!thread.busy) {
this->threads[thread.threadId].busy = true;
++(this->nbActiveThreads);
// wake thread such that it gets the next params and runs them
SetEvent(thread.waitSignal);
break;
}
}
LeaveCriticalSection(&(this->mutex));
}
chỉnh sửa chính xác câu hỏi của bạn ... – neuro