这是我第一个使用线程的程序。我使用C++11标准线程,并在Linux上运行它。
该程序创建两个线程,将向量中的所有元素相加在一起。第一个创建的线程与向量的左侧和,另一个线程与向量的右侧和。
主线程运行到两者都完成为止,将两个和相加在一起,然后打印和。
#include <iostream>
#include <vector>
#include <thread>
void
adder( const std::vector<int> & v, int begin, int end, int & result)
{
for( ; begin < end; ++begin )
{
result = result + v.at( begin );
}
}
int
main()
{
int sum_left = 0;
int sum_right = 0;
std::vector<int> v( 100000000,1); //100 millions
int v_size = v.size();
std::thread t1( adder, v, 0,v_size/2 , std::ref(sum_left) );
std::thread t2( adder, v, v_size/2, v_size, std::ref(sum_right) );
t1.join();
t2.join();
int sum_total = sum_left + sum_right;
std::cout << sum_total << '\n';
return 0;
}发布于 2014-03-28 01:02:45
首先,这是第一次很好地尝试编写一些线程代码。主要的症结在于您正在传入一个int &并返回void。当然,std::thread只运行一些代码,不会返回结果。但是,在C++11线程库中,您可以使用许多东西来返回结果,而不必使用std::ref和引用参数。
在解决这个问题之前,让我们先看看adder函数本身。我将对它进行一系列的改进。首先,您应该尝试使用正确的类型对std::vector进行索引:
using size_type = std::vector<int>::size_type;
int adder( const std::vector<int> & v, size_type begin, size_type end)
{
for( ; begin < end; ++begin )
{
result = result + v.at( begin );
}
}这是可以的,但它可能更通用:如果值没有存储在std::vector中怎么办?相反,模板这样它就可以使用任何支持迭代器概念的东西:
template <typename Iterator>
int adder(Iterator begin, Iterator end)
{
int result = 0;
for(auto it = begin; it != end; ++it) {
result += *it;
}
return result;
}好的,到了那里,但是我们仍然可以改进这一点:如果我们想要对任何类型的数字进行求和,怎么办?(注意,这需要一个#include <iterator>):
template <typename Iterator>
std::iterator_traits<Iterator>::value_type
adder(Iterator begin, Iterator end)
{
std::iterator_traits<Iterator>::value_type result;
for(auto it = begin; it != end; ++it) {
result += *it;
}
return result;
}好的,所以我们不再被锁在vector或int类型中了。但是,这种总结一组值的模式是非常普遍的,并且有一些库功能为我们处理:std::accumulate (注意,这需要一个#include <algorithm>):
template <typename Iterator>
typename std::iterator_traits<Iterator>::value_type
adder(Iterator begin, Iterator end)
{
using T = typename std::iterator_traits<Iterator>::value_type;
return std::accumulate(begin, end, T());
}现在是线程部分。
C++11线程库有一个非常方便的函数,名为std::async。这允许您在线程中运行某些代码,并从中检索结果。它将返回已知的std::future (请注意,这需要一个#include <future>):
template <typename Iterator>
typename std::iterator_traits<Iterator>::value_type
parallel_sum(Iterator begin, Iterator end)
{
using T = typename std::iterator_traits<Iterator>::value_type;
auto midpoint = begin + std::distance(begin, end) / 2;
std::future<T> f1 = std::async(std::launch::async, adder<Iterator>, begin, midpoint);
std::future<T> f2 = std::async(std::launch::async, adder<Iterator>, midpoint, end);
return f1.get() + f2.get();
}然后,我们将如下所示:
int main()
{
std::vector<int> v;
for(int i = 0; i < 100000; ++i) {
v.push_back(i);
}
int total = parallel_sum(v.begin(), v.end());
std::cout << total << "\n";
}这里可能一次就有太多的东西要吸收,但我将详细分析以下要点:
std::accumulate )的功能。std::async而不是通过引用传递参数来存储结果。https://codereview.stackexchange.com/questions/45557
复制相似问题