Потоки 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.