今天使用c++实现了标准库头文件<numeric>中的accumulate函数的并行计算版本,代码如下,注释写的比较详细,仅对其中几点进行描述:

①该实现假定不发生任何异常,故没有对可能产生的异常进行处理

②第42行的语句:

const unsigned int num_thread = std::min((hardware_thread != 0 ? hardware_thread : 2), max_thread);

要运行的线程数是计算出的最大线程数和硬件线程数量的较小值。这是因为若运行的线程数超出了硬件支持的范围,CPU的上下文切换会降低性能。又因为hardware_thread的值可能为0,在这种情况下用户需要自行替换线程的数量,在代码中为2,因为在单核的机器上运行过多的线程会导致性能降低,但过少的线程也会使用户错过可用的并发。

③第44行计算每个线程操作的元素个数时算式可能无法整除,但无须担心,因为最后一个线程将会处理剩下的所有元素,如第68行语句所示:

Accum<Iterator, T>()(block_begin, last, results[num_thread - 1]);

④注意第64行的语句:

threads[i] = thread(Accum<Iterator, T>(), block_begin, block_end, std::ref(results[i]));

传给线程执行的函数的第三个参数增加了std::ref(),该函数包含在头文件<functional>中。在一般情况下,thread对象的构造函数只是简单地拷贝用户提供的参数,然后传递给线程关联的可调用对象。也就是说,该可调用对象接收的是该参数的副本,对其所作的修改无法影响到最初用户所传递的参数。若需要接收参数的引用版本,则需要使用std::ref()函数。

 //实现标准库头文件<numeric>中accumulate函数的并行版本
#include <iostream>
#include <thread>
#include <numeric>
#include <algorithm>
#include <vector>
#include <functional>
#include <utility> using std::thread;
using std::vector;
using std::accumulate;
using std::cout;
using std::endl; template <typename Iterator, typename T> class Accum
{
public:
void operator() (Iterator first, Iterator last, T &sum)
{
sum = std::accumulate(first, last, sum);
}
}; template <typename Iterator, typename T>
T ParallelAccum(Iterator first, Iterator last, T &sum)
{
//计算迭代器中包含的元素数量
const unsigned int len = std::distance(first, last);
//若迭代器中没有元素则直接返回
if (!len)
{
return sum;
}
//每个线程处理的元素的最小数量
const unsigned int min_per_thread = ;
//获取线程的最大数量,向上取整
const unsigned int max_thread = (len - + min_per_thread) / min_per_thread;
//获取机器支持的并发线程数
const unsigned int hardware_thread = thread::hardware_concurrency();
//取上述两者的较小值,同时避免线程数过少
const unsigned int num_thread = std::min((hardware_thread != ? hardware_thread : ), max_thread);
//最终实际上每个线程处理的元素个数
const unsigned int block_size = len / num_thread;
//保存每个线程累加的结果
vector<T> results(num_thread);
//启动比num_thread - 1个线程,因为main函数本身已开启一个线程
vector<thread> threads(num_thread - );
//
cout << "Number of elements: " << len << endl;
cout << "Hardware concurrency: " << hardware_thread << endl;
cout << "Maximum number of threads: " << max_thread << endl;
cout << "Number of threads: " << num_thread << endl;
cout << "Block size: " << block_size << endl;
cout << "Started parallel calculating..." << endl;
//开始并行计算
Iterator block_begin = first;
for (unsigned int i = ; i < (num_thread - ); ++i)
{
Iterator block_end = block_begin;
//将迭代器向前推进一个块,到达当前块的末尾位置
std::advance(block_end, block_size);
//传递参数,通常情况下thread的构造函数将复制所提供的参数,需要将模板参数转为引用
threads[i] = thread(Accum<Iterator, T>(), block_begin, block_end, std::ref(results[i]));
block_begin = block_end;
}
//处理最后一个线程,由于block_size = len / num_thread得到的结果不一定为整数,该线程处理剩余的所有元素
Accum<Iterator, T>()(block_begin, last, results[num_thread - ]);
//对threads中所有线程调用join()
std::for_each(threads.begin(), threads.end(), std::mem_fn(&thread::join));
//
return accumulate(results.begin(), results.end(), sum);
} int main()
{
vector<int> i_vec;
int sum = ;
for (int i = ; i != ; ++i)
{
i_vec.push_back(i);
}
sum = ParallelAccum(i_vec.cbegin(), i_vec.cend(), sum);
cout << "sum = " << sum << endl;
system("pause");
return ;
}

最新文章

  1. “.Net 社区虚拟大会”(dotnetConf) 2016 Day 1 Keynote: Scott Hunter
  2. js自动提示查询添加功能(不是自动补全)
  3. Apache Flink初接触
  4. 文件名保存为.wsf文件即可分析文件夹中每个文件的行数
  5. IIS 7.5最新解析漏洞
  6. Qt编程之mapx组件编程
  7. Metro 页面间跳转报错、打包和安装一个本地的Metro类型应用
  8. 潮流设计:15个创意的 3D 字体版式作品欣赏
  9. Windows创建文件链接
  10. Spring day01
  11. UVA - 1153 Keep the Customer Satisfied(贪心)
  12. 转:sql语句中GROUP BY 和 HAVING和使用 count()
  13. MSSQL 获取指定日期所在星期的第一天和最后一天日期 获取指定日期坐在月的第一天和最后一天
  14. 集合中Set_List必须覆盖 hashCode()与 equals()
  15. Math类的round方法小解
  16. JavaScript正则表达式知识点
  17. postgreSQL可视化工具pgAdmin3 导入表结构和数据
  18. 根据字段获取DataTable包含某个值的数据
  19. VS2017企业版密钥
  20. MySQL基于LVM快照的备份恢复(临时)

热门文章

  1. JavaScript&amp;jQuery获取url参数方法
  2. 20145314郑凯杰 《Java程序设计》第3周学习总结
  3. spring boot加mybatis使用Map返回时,当值为空时属性也会没有(转)
  4. ubuntu下源码安装wget
  5. CentOS7系统安装及环境初始化
  6. Nginx配置X-Forwarded-Proto
  7. Linux 下 YUM 安装 PHP 5.5 (及5.6)
  8. Ad Exchange基本接口和功能
  9. [代码解析]Mask R-CNN介绍与实现(转)
  10. 解题报告:hdu2602 Bone collector 01背包模板