Та же производительность с двумя потоками, как с одним? - PullRequest
0 голосов
/ 29 апреля 2020

Я играю с многопоточностью, чтобы попытаться лучше понять, как реализовать это в другом проекте, и собрал небольшой пример. Код сначала генерирует 10000 строк. Существует функция foo, которая перебирает каждую строку между двумя заданными начальным и конечным индексами, проверяя, присутствует ли символ "a" (просто для некоторого синтетического c load).

При вызове foo в главном потоке с циклом всех 10000 строк время выполнения составляет ~ 72 мс. При использовании двух отдельных потоков th1 и th2 и передаче указателя функции foo вместе с индексом начала и конца (фактически каждый поток обрабатывает половину 10000 строк), я ожидал, что время выполнения будет меньше ~ 72 мс, так как я понял, что каждый поток будет выполняться одновременно, производя время выполнения ~ 36 мс.

Однако время выполнения такое же, как у l oop, проходящего через все 10000 строк в основном потоке. , Может ли кто-нибудь объяснить мне, почему это так?

#include <iostream>
#include <vector>
#include <memory>
#include <map>
#include <optional>
#include <string>
#include <algorithm>
#include <chrono>
#include <thread>
#include <iomanip>
#include <cmath>
#include <limits>
#include <ratio>
#include <thread> 

std::chrono::high_resolution_clock::time_point startTime;

std::vector<std::string> strings;


bool string_contains(std::string needle, std::string haystack)
{
    if (haystack.find(needle) != std::string::npos)
    {
        return true;
    }
    return false;
}

std::string random_string(int len)
{
    std::string str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    std::string newstr;
    int pos;
    while (newstr.size() != len) {
        pos = ((rand() % (str.size() - 1)));
        newstr += str.substr(pos, 1);
    }
    return newstr;
}

const double now()
{
    std::chrono::duration<double> t = std::chrono::duration_cast<std::chrono::duration<double>>(std::chrono::high_resolution_clock::now() - startTime);
    return t.count();
}

void build_strings()
{
    for (size_t i = 0; i < 10000; i++)
    {
        strings.push_back(random_string(20));
    }
}

void foo(size_t start, size_t end, size_t thread)
{
    size_t stringsWithA = 0;
    for (size_t i = start; i < end; i++)
    {
        if (string_contains("a", strings[i]))
        {
            stringsWithA++;
        }
    }
    std::cout << stringsWithA << "\n";
}

int main()
{
    build_strings();

    auto time_a = now();

    foo(0, strings.size(), 0);

    auto time_b = now();

    std::cout << std::setprecision(10) << std::fixed << "main       " << time_b - time_a << "\n";


    time_a = now();
    std::thread th1(foo, 0, strings.size() / 2, 1);
    std::thread th2(foo, strings.size() / 2, strings.size(), 2);

    th1.join();
    th2.join();

    time_b = now();

    std::cout << std::setprecision(10) << std::fixed << "threaded   " << time_b - time_a << "\n";



    std::cin.get();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...