Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Многопоточность и некорректные результаты 
V
    Опции темы
baldman88
Дата 1.10.2018, 10:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 210
Регистрация: 18.1.2009

Репутация: 3
Всего: 7



Добрый день. Есть задача обработки элементов вектора. Вектор не очень большой, но и не маленький (в среднем около 5000 элементов, которые являются небольшими изображениями). Решил применить многопоточность и сделать небольшой тестовый пример (максимально упрощенный). Так вот результаты получаются совсем не те, что ожидаются.
Вот код:
Код

#include <cmath>
#include <vector>
#include <thread>
#include <iostream>
#include <functional>


int test(int x)
{
    return x * x;
}


void print(const std::vector<int>& v)
{
    for (const auto i : v)
    {
        std::cout << i << " ";
    }
    std::cout << std::endl;
}


void print(std::vector<int>::iterator begin, std::vector<int>::iterator end)
{
    auto it = begin;
    while (it != end)
    {
        std::cout << *it << " ";
        ++it;
    }
    std::cout << std::endl;
}


std::vector<int>::iterator for_each(std::vector<int>::iterator first, std::vector<int>::iterator last,
                                    std::vector<int>::iterator result, std::function<int(int)> mapFunctor)
{
    while (first != last)
    {
        *result = mapFunctor(*first);
        ++result;
        ++first;
    }
    return result;
}


std::vector<int>::iterator mapped(std::vector<int>::iterator first, std::vector<int>::iterator last,
                                  std::vector<int>::iterator result, std::function<int(int)> mapFunctor)
{
    auto availableThreads = std::thread::hardware_concurrency();
    if (availableThreads < 2)
    {
        for_each(first, last, result, mapFunctor);
    }
    else
    {
        const auto totalSize = std::distance(first, last);
        const auto blockSize = static_cast<size_t>(std::ceil(1.0 * totalSize / availableThreads));
        std::vector<std::thread> threads;
        std::vector<std::vector<int>> results;
        auto current = first;
        for (unsigned int i = 0; i < (availableThreads - 1); ++i)
        {
            auto blockStart = current;
            auto blockEnd = blockStart;
            std::advance(blockEnd, blockSize);
            current = blockEnd;
            results.emplace_back(std::vector<int>(blockSize));
            threads.emplace_back(
                    std::thread(for_each, std::ref(blockStart),
                                std::ref(blockEnd), results.at(i).begin(), mapFunctor));
        }
        result = for_each(current, last, result, mapFunctor);
        for (unsigned int i = 0; i < threads.size(); ++i)
        {
            if (threads[i].joinable())
            {
                threads[i].join();
            }
            print(results.at(i));
            result = std::copy(results.at(i).begin(), results.at(i).end(), result);
        }
    }
    return result;
}


int main()
{
    std::vector<int> v;
    for (unsigned int i = 1; i < 41; ++i)
    {
        v.emplace_back(i);
    }
    std::vector<int> v2;
    v2.resize(v.size());
    print(v);
    mapped(v.begin(), v.end(), v2.begin(), test);
    print(v2);
    return 0;
}

В итоге получаю, примерно, вот такой вывод:
Код

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
121 144 169 196 225
121 144 169 196 225
256 289 324 361 400
441 484 529 576 625
676 729 784 841 900
961 1024 1089 1156 1225
961 1024 1089 1156 1225
1296 1369 1444 1521 1600 121 144 169 196 225 121 144 169 196 225 256 289 324 361 400 441 484 529 576 625 676 729 784 841 900 961 1024 1089 1156 1225 961 1024 1089 1156 1225

Первая строка это исходные элементы, со второй по восьмую -- результат обработки блоков в разных потоках, девятая -- результирующий вектор.

Подскажите, пожалуйста, что я не учел?
PM MAIL   Вверх
baldman88
Дата 2.10.2018, 10:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 210
Регистрация: 18.1.2009

Репутация: 3
Всего: 7



Проблема была в том, что я, зачем-то, передавал в поток итераторы, обернутые в std::ref.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0969 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.