Производительность контейнеров C ++ во время выполнения потока - PullRequest
0 голосов
/ 04 августа 2020

Я работаю над проектом, который использует несколько потоков для распараллеливания задач. Во время разработки я заметил, что производительность операций с контейнером std :: list, например pop_front () или push_back (), значительно медленнее при выполнении в потоке по сравнению с выполнением в одном потоке. См. Фрагмент кода ниже:

#include <iostream>
#include <chrono>
#include <vector>
#include <string>
#include <thread>
#include <list>

using namespace std;

void SingleThreadedList()
{
    auto t1 = std::chrono::high_resolution_clock::now();

    for(int i=0; i<2; i++)
    {
        list<char> l;

        for(int j=0; j<10000; j++)
        {
            l.push_back('c');
            l.pop_front();
        }
    }

    auto t2 = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>( t2 - t1 ).count();
    std::cout << "duration single thread: " <<  duration << endl;
}

void MultiThreadedList()
{
    auto t1 = std::chrono::high_resolution_clock::now();

    auto lambda_fkt = []() {

        list<char> l;

        for(int i=0; i<10000; i++)
        {
            l.push_back('c');
            l.pop_front();
        }
    };

    vector<thread*> thread_array;
    for (int i=0; i<2; ++i)
    {
        thread *th = new thread(lambda_fkt);
        thread_array.push_back(th);
    }

    for(auto t : thread_array)
    {
        t->join();
    }

    auto t2 = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>( t2 - t1 ).count();
    std::cout << "duration multi thread: " <<  duration << endl;

    for(auto t : thread_array)
    {
        delete t;
    }
}

int main() {
    SingleThreadedList();
    MultiThreadedList();
}

код дает следующий результат:

duration single thread: 4589
duration multi thread: 245483

Вариант с одним потоком занимает 4 мс, но как только потоки созданы, выполнение занимает больше чем 200 мс! Я не могу представить, чтобы стандартные библиотечные контейнеры показывали такую ​​разницу в производительности в зависимости от контекста выполнения. Поэтому мне интересно, может ли кто-нибудь объяснить мне, что происходит в этом коде и как я могу избежать снижения производительности в пределах thread? Спасибо!

PS: Когда я удаляю операции со списком из этого примера и добавляю, например, некоторую простую математику, код быстро показывает ожидаемое поведение: многопоточный вариант становится быстрее, если вычисление разделено между несколькими потоками , таким образом используя несколько ядер для получения результата.

...