첫 번째 버전 인 두 개의 스레드 선택 정렬은 모든 반복마다 새 스레드를 시작합니다.멀티 스레드 정렬 알고리즘을 효율적으로 구현하는 데 필요한 핵심 요소는 무엇입니까? 순진한 구현이 제대로 작동하지 않습니다.
일부 비교 (왼쪽 - 하나 개의 스레드를 마우스 오른쪽 - 두 개의 스레드 버전, 시간 - MS) : 두 개의 스레드가 빠르게 작업
Size: 500 time 1 time 5
Size: 1000 time 1 time 9
Size: 1500 time 4 time 12
Size: 2000 time 5 time 16
Size: 2500 time 10 time 22
Size: 3000 time 14 time 26
Size: 3500 time 19 time 30
Size: 4000 time 24 time 36
Size: 4500 time 30 time 43
Size: 5000 time 37 time 49
Size: 5500 time 46 time 57
Size: 6000 time 55 time 66
Size: 6500 time 63 time 76
Size: 7000 time 74 time 80
Size: 7500 time 85 time 92
Size: 8000 time 96 time 102
Size: 8500 time 108 time 109
Size: 9000 time 122 time 124
Size: 9500 time 135 time 132
Size: 10000 time 150 time 144
Size: 10500 time 165 time 156
Size: 11000 time 181 time 174
Size: 11500 time 200 time 177
Size: 12000 time 218 time 195
Size: 12500 time 235 time 205
Size: 13000 time 255 time 214
Size: 13500 time 273 time 226
Size: 14000 time 296 time 245
9500 크기의 배열 후. 두 번째 구현에서는 스레드가 한 번 시작됩니다. 그러나 그것은 믿을 수없는 성과를 가지고 있습니다.
내 CPU에는 4 개의 코어가 있습니다.
Size: 0 time 0 time 0
Size: 50 time 0 time 151
Size: 100 time 0 time 1276
Size: 150 time 0 time 2089
Size: 200 time 0 time 3925
Size: 250 time 0 time 5303
코드 :
//one thread
template<class ItType>
void selectionSortThreadsHelper2(ItType beg, ItType end)
{
//sorting element by element
for (auto it = beg; it != end; ++it) {
ItType middleIt = it + std::distance(it, end)/2;
auto search = [&] { return std::min_element(it, middleIt); };
//search
std::future<ItType> minFirstHalfResult(std::async(std::launch::async , search));
//wait searching
ItType minSecondHalfIt = std::min_element(middleIt, end);
ItType minFirstHalfIt = minFirstHalfResult.get();
//swap if
ItType minIt = *minFirstHalfIt < *minSecondHalfIt ? minFirstHalfIt : minSecondHalfIt;
if (minIt != it)
std::iter_swap(minIt, it);
}
}
//two thread
template<class ItType>
void selectionSortThreadsHelper3(ItType beg, ItType end)
{
bool quit = false;
bool readyFlag = false;
bool processed = false;
std::mutex readyMutex;
std::condition_variable readyCondVar;
ItType it;
ItType middleIt;
ItType minFirstHalfIt;
auto search = [&]() {
while (true) {
std::unique_lock<std::mutex> ul(readyMutex);
readyCondVar.wait(ul, [&] {return readyFlag; });
if (quit)
return;
minFirstHalfIt = std::min_element(it, middleIt);
processed = true;
ul.unlock();
readyCondVar.notify_one();
}
};
std::future<void> f(std::async(std::launch::async, search));
//sorting element by element
for (it = beg; it != end; ++it) {
middleIt = it + std::distance(it, end)/2;
//say second thread to start searching
{
std::lock_guard<std::mutex> lg(readyMutex);
readyFlag = true;
}
readyCondVar.notify_one();
//std::this_thread::yield();
ItType minSecondHalfIt = std::min_element(middleIt, end);
//wait second thread
{
std::unique_lock<std::mutex> ul(readyMutex);
readyCondVar.wait(ul, [&] { return processed; });
processed = false;
readyFlag = false;
}
readyCondVar.notify_all();
//swap if
ItType minIt = *minFirstHalfIt < *minSecondHalfIt ? minFirstHalfIt : minSecondHalfIt;
if (minIt != it)
std::iter_swap(minIt, it);
}
//quit thread
{
std::lock_guard<std::mutex> lg(readyMutex);
readyFlag = true;
quit = true;
}
readyCondVar.notify_all();
f.get();
}
키가 사용 가능한 코어 수와 정확하게 균형을 잡습니다. –
코드에서 스레드를 전혀 사용하지 않습니다. 'std :: async'를 호출하여 미래를 만들고 나서, 미래가 끝나고 결과를 전달할 때까지 기다린다. 그것은 스레드 또는 선물없이 순차적으로 검색을 수행하는 것과 다르지 않습니다. –
아, 문제가 있습니다. 나는 그것을 해결하고 두 개의 스레드 버전이 더 빨리 9000 사이즈 배열로 작동한다. 하지만 두 번째 구현은 무엇입니까? – Stark