проблемы с производительностью в параллельном слиянии C ++
Я попытался написать параллельную реализацию mergesort, используя потоки и шаблоны. Соответствующий код указан ниже.
Я сравнил производительность с сортировкой из C ++ STL. Мой код в 6 раз медленнее, чем std :: sort, когда не создаются потоки. Играя с переменной maxthreads (и / или FACTOR), я смог удвоить производительность, так что в лучшем случае я в 3 раза медленнее, чем std :: sort. Я пробовал код на 16-ядерном многопроцессорном компьютере.
htop показывает, что ядра используются как положено, но почему не хватает производительности и я не чувствую параллелизма в общем времени выполнения?
Есть ли ошибка?
Спасибо за ответ.
#define FACTOR 1
static unsigned int maxthreads = FACTOR * std::thread::hardware_concurrency();
unsigned int workers=0;
std::mutex g_mutex;
template <typename T>
std::vector<T>* mergesort_inplace_multithreading(
typename std::vector<T>::iterator* listbegin,
typename std::vector<T>::iterator *listend,
std::vector<T>* listarg)
{
if (*listbegin == *listend)
{
return listarg;
}
else if (*listend == *listbegin + 1)
{
return listarg;
}
else
{
size_t offset = std::distance(*listbegin, *listend)/2;
typename std::vector<T>::iterator listhalf = *listbegin + offset;
g_mutex.lock();
if (::workers <= maxthreads-2 and maxthreads >=2)
{
workers += 2;
g_mutex.unlock();
std::thread first_thread(mergesort_inplace_multithreading<T>, listbegin, &listhalf, listarg);
std::thread second_thread(mergesort_inplace_multithreading<T>, &listhalf, listend, listarg);
first_thread.join();
second_thread.join();
g_mutex.lock();
workers -= 2;
g_mutex.unlock();
}
else
{
g_mutex.unlock();
mergesort_inplace_multithreading<T>(listbegin, &listhalf, listarg);
mergesort_inplace_multithreading<T>(&listhalf, listend, listarg);
}
typename std::vector<T> result;
typename std::vector<T>::iterator lo_sorted_it = *listbegin;
typename std::vector<T>::iterator hi_sorted_it = listhalf;
typename std::vector<T>::iterator lo_sortedend = listhalf;
typename std::vector<T>::iterator hi_sortedend = *listend;
while (lo_sorted_it != lo_sortedend and hi_sorted_it != hi_sortedend)
{
if (*lo_sorted_it <= *hi_sorted_it)
{
result.push_back(*lo_sorted_it);
++lo_sorted_it;
}
else
{
result.push_back(*hi_sorted_it);
++hi_sorted_it;
}
}//end while
if (lo_sorted_it != lo_sortedend)
{
//assert(hi_sorted_it == hi_sortedend);
result.insert(result.end(), lo_sorted_it, lo_sortedend);
}
else
{
//assert(lo_sorted_it == lo_sortedend);
result.insert(result.end(), hi_sorted_it, hi_sortedend);
}
std::copy(result.begin(), result.end(), *listbegin);
return listarg;
}
}
int main()
{
//some tests
}