返回> 网站首页
进入多核时代的C++
yoours2011-01-12 13:38:33
简介一边听听音乐,一边写写文章。
本文介绍了多核时代下C++遇到的问题以及应对手段,最后简单介绍了怎样使用Intel Thread Building Blocks来让C++充分利用多核CPU的处理能力。
- 死锁 编写多线程必然会遇到同步问题,如果同步控制出现问题,就可能出现死锁或脏数据。
- 线程之间通信 使用何种机制在多个线程之间通信?即要保证通信数据同步又要保证效率。
- 负载平衡 分配到每个线程的工作量要尽量平衡,避免一个线程忙一个线程闲的情形发生。
- 资源匹配 程序应该使用多少个线程?过少的线程不能充分利用CPU的多核优势,而过多的线程会造成线程调度过于频繁同样会降低效率。
TBB的功能和优势
功能 | 优势 |
---|---|
基于任务的并行化 | 在逻辑任务而非物理线程的角度来指定线程功能
|
并行算法 | 从库中选择高效并行算法模板,即可快速地获得多核处理器带来的优势。
|
跨平台支持 | 编写一次应用就可以部署到多个操作系统中。
|
程序库级解决方案 | 只需花费很小的精力就可得到高优化的并行功能。
|
高并发容器 | 优化处理器的能力实现任务并发
|
示例:
- #include <iostream>
- #include <algorithm>
- #include <vector>
- #include <list>
- #include <math.h>
- #include <tbb/task_scheduler_init.h>
- #include <tbb/blocked_range.h>
- #include <tbb/parallel_for.h>
- #include <tbb/pipeline.h>
- #include <tbb/tick_count.h>
- //-----------------随机存取迭代器版本-------------------------------------
- //both_random_helper,作用:测试两个模板是否都是random_access_iterator_tag
- //是则Iter_cat返回random_access_iterator_tag
- //否则返回forward_iterator_tag
- template<class _Cat1, class _Cat2>
- struct both_random_helper{
- typedef std::forward_iterator_tag Iter_cat;
- };
- template<>
- struct both_random_helper<
- std::random_access_iterator_tag,
- std::random_access_iterator_tag>{
- typedef std::random_access_iterator_tag Iter_cat;
- };
- // 用于存放一对迭代器
- template<class _InIt, class _OutIt>
- struct Iter_pair{
- _InIt m_in;
- _OutIt m_out;
- Iter_pair(_InIt _in, _OutIt _out)
- :m_in(_in),m_out(_out){}
- //支持blocked_range拆分
- Iter_pair operator+(size_t off) const
- {
- return Iter_pair(m_in+off, m_out+off);
- }
- size_t operator-(Iter_pair rhs) const
- {
- return m_in-rhs.m_in;
- }
- bool operator<(Iter_pair rhs) const
- {
- return m_in<rhs.m_in;
- }
- };
- // 随机存取迭代器版本
- template<class _InIt, class _OutIt, class _Fn1>
- struct op_parallel_transform{
- op_parallel_transform(_Fn1 _Func)
- :m_Func(_Func){}
- void operator()(const tbb::blocked_range<Iter_pair<_InIt,_OutIt> > &r) const
- {
- std::transform(r.begin().m_in, r.end().m_in, r.begin().m_out, m_Func);
- }
- private:
- _Fn1 m_Func;
- };
- template<class _InIt, class _OutIt, class _Fn1>
- _OutIt _parallel_transform(_InIt _First, _InIt _Last, _OutIt _Dest,
- _Fn1 _Func, std::random_access_iterator_tag)
- {
- // 使用parallel_for来处理
- typedef typename Iter_pair<_InIt,_OutIt> iter_pair_type;
- _OutIt LastDest = _Dest + (_Last - _First);
- iter_pair_type begin(_First, _Dest);
- iter_pair_type end(_Last, LastDest);
- tbb::blocked_range<iter_pair_type> x(begin, end);
- tbb::parallel_for(x, op_parallel_transform<_InIt,_OutIt,_Fn1>(_Func), tbb::auto_partitioner());
- return LastDest;
- }
- //-----------------顺序存取迭代器版本-------------------------------------
- template<class _InIt>
- struct filter_in : tbb::filter{
- filter_in(_InIt _First, _InIt _Last)
- :tbb::filter(true),m_First(_First), m_Last(_Last){}
- void* operator()(void*)
- {
- if(m_First==m_Last) return NULL;
- void* p = &(*m_First);
- ++m_First;
- return p;
- }
- private:
- _InIt m_First, m_Last;
- };
- template<class _Fn1>
- struct filter_process : tbb::filter{
- typedef typename _Fn1::result_type r_type;
- typedef typename _Fn1::argument_type a_type;
- filter_process(_Fn1 _Func)
- :tbb::filter(false),m_Func(_Func){}
- void* operator()(void* data)
- {
- a_type &at = *(a_type*)data;
- m_r = m_Func( at );
- return &m_r;
- }
- private:
- _Fn1 m_Func;
- r_type m_r;
- };
- template<class _OutIt, class _DataType>
- struct filter_out : tbb::filter{
- filter_out(_OutIt _Dest)
- :tbb::filter(true),m_Dest(_Dest){}
- void* operator()(void* data)
- {
- _DataType *p = (_DataType*) data;
- *m_Dest = *p;
- ++m_Dest;
- return NULL;
- }
- private:
- _OutIt m_Dest;
- };
- template<class _InIt, class _OutIt, class _Fn1>
- _OutIt _parallel_transform(_InIt _First, _InIt _Last, _OutIt _Dest,
- _Fn1 _Func, std::forward_iterator_tag)
- {
- // 使用管线pipeline来处理
- tbb::pipeline pipeline;
- filter_in<_InIt> f1(_First, _Last);
- filter_process<_Fn1> f2(_Func);
- filter_out<_OutIt, _Fn1::result_type> f3(_Dest);
- pipeline.add_filter(f1);
- pipeline.add_filter(f2);
- pipeline.add_filter(f3);
- pipeline.run(3);
- return _Dest;
- }
- //----------------------parallel_transform----------------------------
- template<class _InIt, class _OutIt, class _Fn1>
- inline
- _OutIt parallel_transform(_InIt _First, _InIt _Last, _OutIt _Dest, _Fn1 _Func)
- {
- typedef typename std::iterator_traits<_InIt>::iterator_category cat1;
- typedef typename std::iterator_traits<_OutIt>::iterator_category cat2;
- return _parallel_transform(_First, _Last, _Dest,
- _Func, both_random_helper<cat1,cat2>::Iter_cat());
- }
- // 测试代码
- struct SinFunctor
- :std::unary_function<double, double>{
- double operator()(double &d) const
- {
- // 高强度运算
- double sum = 0;
- for(int i=0; i<10000; i++) sum += sin(i*d);
- return sum;
- }
- };
- int main()
- {
- // 随机存取迭代
- std::vector<double> a(10000,1.5);
- // 顺序存取迭代
- std::list<double> b(10000,1.5);
- tbb::task_scheduler_init init;
- tbb::tick_count t0,t1;
- t0 = tbb::tick_count::now();
- parallel_transform(a.begin(), a.end(), a.begin(), SinFunctor());
- t1 = tbb::tick_count::now();
- std::cout << "并行(随机迭代)" << (t1 - t0).seconds() << std::endl;
- t0 = tbb::tick_count::now();
- std::transform(a.begin(), a.end(), a.begin(), SinFunctor());
- t1 = tbb::tick_count::now();
- std::cout << "原版(随机迭代)" << (t1 - t0).seconds() << std::endl;
- t0 = tbb::tick_count::now();
- parallel_transform(b.begin(), b.end(), b.begin(), SinFunctor());
- t1 = tbb::tick_count::now();
- std::cout << "并行(顺序迭代)" << (t1 - t0).seconds() << std::endl;
- t0 = tbb::tick_count::now();
- std::transform(b.begin(), b.end(), b.begin(), SinFunctor());
- t1 = tbb::tick_count::now();
- std::cout << "原版(顺序迭代)"<< (t1 - t0).seconds() << std::endl;
- std::cin.get();
- return 0;
- }
并行(随机迭代)3.17299 原版(随机迭代)5.41531 并行(顺序迭代)3.13054 原版(顺序迭代)5.33182
文章评论
1515人参与,0条评论