Потоки OpenMP vs С++ 11
В следующем примере потоки С++ 11 занимают около 50 секунд для выполнения, но потоки OMP - всего 5 секунд. Любые идеи почему? (Я могу заверить вас, что это все еще верно, если вы выполняете настоящую работу вместо doNothing
, или если вы делаете это в другом порядке и т.д.) Я тоже на 16-ядерном компьютере.
#include <iostream>
#include <omp.h>
#include <chrono>
#include <vector>
#include <thread>
using namespace std;
void doNothing() {}
int run(int algorithmToRun)
{
auto startTime = std::chrono::system_clock::now();
for(int j=1; j<100000; ++j)
{
if(algorithmToRun == 1)
{
vector<thread> threads;
for(int i=0; i<16; i++)
{
threads.push_back(thread(doNothing));
}
for(auto& thread : threads) thread.join();
}
else if(algorithmToRun == 2)
{
#pragma omp parallel for num_threads(16)
for(unsigned i=0; i<16; i++)
{
doNothing();
}
}
}
auto endTime = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = endTime - startTime;
return elapsed_seconds.count();
}
int main()
{
int cppt = run(1);
int ompt = run(2);
cout<<cppt<<endl;
cout<<ompt<<endl;
return 0;
}
Ответы
Ответ 1
OpenMP пулы потоков для своих Pragmas (также здесь и здесь). Скручивание и срывание нитей дорого. OpenMP избегает этих накладных расходов, поэтому все, что он делает, - это фактическая работа и минимальное перемещение памяти с состоянием общей памяти. В коде Threads
вы вращаетесь и разрываете новый набор из 16 потоков на каждой итерации.
Ответ 2
Я пробовал код из 100 циклов в
Выбор правильной структуры потоков, и потребовалось
OpenMP 0.0727, библиотека Intel TBB 0.6759 и С++ 0.5962 миллисекунды.
Я также применил то, что предложил AruisDante;
void nested_loop(int max_i, int band)
{
for (int i = 0; i < max_i; i++)
{
doNothing(band);
}
}
...
else if (algorithmToRun == 5)
{
thread bristle(nested_loop, max_i, band);
bristle.join();
}
Этот код похож на меньшее время, чем исходная секция потока С++ 11.