В качестве упражнения, чтобы узнать о std::async
, я написал небольшую программу, которая вычисляет сумму большого vector<int>
, распределенного вокруг большого количества потоков.
Мой следующий код выглядит следующим образом
#include <iostream>
#include <vector>
#include <future>
#include <chrono>
typedef unsigned long long int myint;
// Calculate sum of part of the elements in a vector
myint partialSum(const std::vector<myint>& v, int start, int end)
{
myint sum(0);
for(int i=start; i<=end; ++i)
{
sum += v[i];
}
return sum;
}
int main()
{
const int nThreads = 100;
const int sizePerThread = 100000;
const int vectorSize = nThreads * sizePerThread;
std::vector<myint> v(vectorSize);
std::vector<std::future<myint>> partial(nThreads);
myint tot = 0;
// Fill vector
for(int i=0; i<vectorSize; ++i)
{
v[i] = i+1;
}
std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::now();
// Start threads
for( int t=0; t < nThreads; ++t)
{
partial[t] = std::async( std::launch::async, partialSum, v, t*sizePerThread, (t+1)*sizePerThread -1);
}
// Sum total
for( int t=0; t < nThreads; ++t)
{
myint ps = partial[t].get();
std::cout << t << ":\t" << ps << std::endl;
tot += ps;
}
std::cout << "Sum:\t" << tot << std::endl;
std::chrono::steady_clock::time_point endTime = std::chrono::steady_clock::now();
std::cout << "Time difference = " << std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count() <<std::endl;
}
Мой вопрос касается вызовов функции partialSum
, а затем, в особенности, как передается большой вектор. Функция вызывается следующим образом:
partial[t] = std::async( std::launch::async, partialSum, v, t*sizePerThread, (t+1)*sizePerThread -1);
с определением следующим образом
myint partialSum(const std::vector<myint>& v, int start, int end)
При таком подходе расчет относительно медленный. Если я использую std::ref(v)
в вызове функции std::async
, моя функция намного быстрее и эффективнее. Это все еще имеет смысл для меня.
Однако, если я еще вызываю v
вместо std::ref(v)
, но заменяю функцию
myint partialSum(std::vector<myint> v, int start, int end)
программа также работает намного быстрее (и использует меньше памяти). Я не понимаю, почему реализация const ref медленнее. Как компилятор исправляет это без каких-либо ссылок?
При реализации const ref эта программа обычно занимает 6,2 секунды для запуска, без 3.0. (Обратите внимание, что с константой ref и std::ref
для меня это работает на 0,2 секунды)
Я компилирую с помощью g++ -Wall -pedantic
, используя (добавление -O3
при передаче только v
демонстрирует тот же эффект)
g++ --version
g++ (Rev1, построенный по проекту MSYS2). 6.3.0 Copyright (C) 2016 Free Software Foundation, Inc. Это бесплатное программное обеспечение; см. источник условий копирования. Здесь нет гарантия; даже для КОММЕРЧЕСКОЙ ЦЕННОСТИ или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННОЙ ЦЕЛИ.