<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>中文 &#187; Waiting4you</title>
	<atom:link href="http://software.intel.com/zh-cn/blogs/author/waiting4you/feed/" rel="self" type="application/rss+xml" />
	<link>http://software.intel.com/zh-cn/blogs</link>
	<description></description>
	<lastBuildDate>Sat, 26 May 2012 06:34:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>进入多核时代的C++</title>
		<link>http://software.intel.com/zh-cn/blogs/2009/05/04/c/</link>
		<comments>http://software.intel.com/zh-cn/blogs/2009/05/04/c/#comments</comments>
		<pubDate>Mon, 04 May 2009 07:25:56 +0000</pubDate>
		<dc:creator>Waiting4you</dc:creator>
				<category><![CDATA[博客征文专栏]]></category>

		<guid isPermaLink="false">http://software.intel.com/zh-cn/blogs/2009/05/04/c/</guid>
		<description><![CDATA[几年之前，CPU的性能还主要取决于CPU的主频，经过超摩尔定律的发展后，没过多长时间CPU的主频速度就已接近“极限”，使得单单靠提高CPU的主频来提升性能变得非常困难。 目前，Intel、AMD等CPU生产商都转而采用了多核技术来提升CPU性能，甚至提出了群核CPU的概念。这意味着，要充分发挥多核CPU的性能，程序就必须采用多线程并发计算的方式，传统的串行程序将会极大地浪费多核CPU的运算能力！ C++是上世纪80年代诞生的语言，它的前身是同样风靡全球的C语言。一直以来它都以代码效率卓越著称，进入多核时代后，因为C++标准库没有提供多线程支持，要用C++开发出充分利用多核CPU的程序将面临很大挑战。 于是，在C++社区出现了不少优秀的库以支持并行编程，如各种跨平台的线程库，OpenMP，Clik++等。另一方面，微软也从Win2K开始不断地加入线程池API（如QueueUserWorkItem），C++09标准也明确地表示要加入多线程的支持。 使用线程库编写并行程序的优点是可以精确调度各个线程，并且可以在所有C++编译器里使用。不过要充分发挥多核CPU的性能，还要考虑很多因素，主要难点有： 死锁    编写多线程必然会遇到同步问题，如果同步控制出现问题，就可能出现死锁或脏数据。 线程之间通信    使用何种机制在多个线程之间通信？即要保证通信数据同步又要保证效率。 负载平衡    分配到每个线程的工作量要尽量平衡，避免一个线程忙一个线程闲的情形发生。 资源匹配    程序应该使用多少个线程？过少的线程不能充分利用CPU的多核优势，而过多的线程会造成线程调度过于频繁同样会降低效率。 OpenMP是目前比较流行的C++并行编程方式，它通过在代码中插入专用的pragma编译指令来指示编译器把串行代码编译成并行程序。 它的优点是易于使用，几乎不用修改原代码就可对老程序进行并发支持的改造。问题是它必须要有编译器的支持，尽管目前不少编译器都提供了OpenMP的支持，但它毕竟不是C++的一部分，甚至它都不是真正意义上的C++库。使用OpenMP的C++代码看上去总是有些怪异（个人观点^_^）。 现在，我们又有了一个新选择：Intel Thread Building Blocks（TBB，线程构建模块）。TBB是一个开源的C++模板库，能够运行在 Windows、Linux、Macintosh以及UNIX等系统上，只要是标准的C++编译器都可以使用它。 TBB的功能和优势 功能 优势 基于任务的并行化 在逻辑任务而非物理线程的角度来指定线程功能 让开发者关注更高层的可扩展任务级模式而非底层的线程机制 使用被证实可有效利用多内核的数据分解提取技术 自动负载平衡 高效地支持嵌套并行化，允许从一个并行组件中建立出一个新的并行组件 并行算法 从库中选择高效并行算法模板，即可快速地获得多核处理器带来的优势。 快速应用为并行性能及可量测性而设计的算法。 范型模板让你轻易地把它们定制成你所需要的算法。 支持简单插件部署到应用中提升软件速度，优化内核和本地缓存。 依靠预置的并行结构，在很多情况下都能减少生产多线程软件的工作量。 跨平台支持 编写一次应用就可以部署到多个操作系统中。 为32位和64位的Windows*、Linux* 和 Mac OS* X 平台提供一种解决方案。 支持Intel、Microsoft及GNU的业界领先的编译器。 加快在多种多核平台中部署应用软件的速度。 程序库级解决方案 只需花费很小的精力就可得到高优化的并行功能。 你的 C++ 应用程序只需调用Intel Threading Building Blocks 库。 标准 [...]]]></description>
			<content:encoded><![CDATA[<p>几年之前，CPU的性能还主要取决于CPU的主频，经过超摩尔定律的发展后，没过多长时间CPU的主频速度就已接近“极限”，使得单单靠提高CPU的主频来提升性能变得非常困难。</p>
<p>目前，Intel、AMD等CPU生产商都转而采用了多核技术来提升CPU性能，甚至提出了群核CPU的概念。这意味着，要充分发挥多核CPU的性能，程序就必须采用多线程并发计算的方式，传统的串行程序将会极大地浪费多核CPU的运算能力！<br />
C++是上世纪80年代诞生的语言，它的前身是同样风靡全球的C语言。一直以来它都以代码效率卓越著称，进入多核时代后，因为C++标准库没有提供多线程支持，要用C++开发出充分利用多核CPU的程序将面临很大挑战。<br />
于是，在C++社区出现了不少优秀的库以支持并行编程，如各种跨平台的线程库，OpenMP，Clik++等。另一方面，微软也从Win2K开始不断地加入线程池API（如QueueUserWorkItem），C++09标准也明确地表示要加入多线程的支持。</p>
<p>使用线程库编写并行程序的优点是可以精确调度各个线程，并且可以在所有C++编译器里使用。不过要充分发挥多核CPU的性能，还要考虑很多因素，主要难点有：</p>
<ul>
<li>死锁    编写多线程必然会遇到同步问题，如果同步控制出现问题，就可能出现死锁或脏数据。</li>
<li>线程之间通信    使用何种机制在多个线程之间通信？即要保证通信数据同步又要保证效率。</li>
<li>负载平衡    分配到每个线程的工作量要尽量平衡，避免一个线程忙一个线程闲的情形发生。</li>
<li>资源匹配    程序应该使用多少个线程？过少的线程不能充分利用CPU的多核优势，而过多的线程会造成线程调度过于频繁同样会降低效率。</li>
</ul>
<p>OpenMP是目前比较流行的C++并行编程方式，它通过在代码中插入专用的pragma编译指令来指示编译器把串行代码编译成并行程序。<br />
它的优点是易于使用，几乎不用修改原代码就可对老程序进行并发支持的改造。问题是它必须要有编译器的支持，尽管目前不少编译器都提供了OpenMP的支持，但它毕竟不是C++的一部分，甚至它都不是真正意义上的C++库。使用OpenMP的C++代码看上去总是有些怪异（个人观点^_^）。</p>
<p>现在，我们又有了一个新选择：Intel Thread Building Blocks（TBB，线程构建模块）。TBB是一个开源的C++模板库，能够运行在 Windows、Linux、Macintosh以及UNIX等系统上，只要是标准的C++编译器都可以使用它。</p>
<h3>TBB的功能和优势</h3>
<table style="border: #4574b9 1px solid;" border="1">
<tbody>
<tr>
<th>功能</th>
<th>优势</th>
</tr>
<tr>
<td>基于任务的并行化</td>
<td>在逻辑任务而非物理线程的角度来指定线程功能</p>
<ul>
<li>让开发者关注更高层的可扩展任务级模式而非底层的线程机制</li>
<li>使用被证实可有效利用多内核的数据分解提取技术</li>
<li>自动负载平衡</li>
<li>高效地支持嵌套并行化，允许从一个并行组件中建立出一个新的并行组件</li>
</ul>
</td>
</tr>
<tr>
<td>并行算法</td>
<td>从库中选择高效并行算法模板，即可快速地获得多核处理器带来的优势。</p>
<ul>
<li>快速应用为并行性能及可量测性而设计的算法。</li>
<li>范型模板让你轻易地把它们定制成你所需要的算法。</li>
<li>支持简单插件部署到应用中提升软件速度，优化内核和本地缓存。</li>
<li>依靠预置的并行结构，在很多情况下都能减少生产多线程软件的工作量。</li>
</ul>
</td>
</tr>
<tr>
<td>跨平台支持</td>
<td>编写一次应用就可以部署到多个操作系统中。</p>
<ul>
<li>为32位和64位的Windows*、Linux* 和 Mac OS* X 平台提供一种解决方案。</li>
<li>支持Intel、Microsoft及GNU的业界领先的编译器。</li>
<li>加快在多种多核平台中部署应用软件的速度。</li>
</ul>
</td>
</tr>
<tr>
<td>程序库级解决方案</td>
<td>只需花费很小的精力就可得到高优化的并行功能。</p>
<ul>
<li>你的 C++ 应用程序只需调用Intel Threading Building Blocks 库。</li>
<li>标准 C++ - 不需要使用新语言重写代码。</li>
<li>兼容其它线程包。</li>
<li>可无限制地和你的软件一起分发运行时库。</li>
<li>无缝整合到已有的开发环境中。</li>
</ul>
</td>
</tr>
<tr>
<td>高并发容器</td>
<td>优化处理器的能力实现任务并发</p>
<ul>
<li>使用线程安全并且高并发的接口简化多线程应用的开发。</li>
<li>使用预测试的数据结构提升应用软件质量。</li>
<li>更高效率的内核或处理器多路执行来提升应用软件性能。</li>
</ul>
</td>
</tr>
</tbody>
</table>
<h3>示例：</h3>
<p>用TBB写并行transform代替原std::transform</p>
<div class="HighLighter">
<div class="dp-highlighter">
<ol class="dp-cpp">
<li class="alt"><span><span class="preprocessor">#include &lt;iostream&gt;</span></span></li>
<li><span><span class="preprocessor">#include &lt;algorithm&gt;</span></span></li>
<li class="alt"><span><span class="preprocessor">#include &lt;vector&gt;</span></span></li>
<li><span><span class="preprocessor">#include &lt;list&gt;</span></span></li>
<li class="alt"><span><span class="preprocessor">#include &lt;math.h&gt;</span></span></li>
<li><span><span class="preprocessor">#include &lt;tbb/task_scheduler_init.h&gt;</span></span></li>
<li class="alt"><span><span class="preprocessor">#include &lt;tbb/blocked_range.h&gt;</span></span></li>
<li><span><span class="preprocessor">#include &lt;tbb/parallel_for.h&gt;</span></span></li>
<li class="alt"><span><span class="preprocessor">#include &lt;tbb/pipeline.h&gt;</span></span></li>
<li><span><span class="preprocessor">#include &lt;tbb/tick_count.h&gt;</span></span></li>
<li><span><span class="comment">//-----------------随机存取迭代器版本-------------------------------------</span></span></li>
<li class="alt"><span><span class="comment">//both_random_helper，作用:测试两个模板是否都是random_access_iterator_tag</span></span></li>
<li><span><span class="comment">//是则Iter_cat返回random_access_iterator_tag</span></span></li>
<li class="alt"><span><span class="comment">//否则返回forward_iterator_tag</span></span></li>
<li><span><span class="keyword">template</span><span>&lt;</span><span class="keyword">class</span><span> _Cat1, </span><span class="keyword">class</span><span> _Cat2&gt;</span></span></li>
<li class="alt"><span><span class="keyword">struct</span><span> both_random_helper{</span></span></li>
<li><span> <span class="keyword">typedef</span><span> std::forward_iterator_tag Iter_cat;</span></span></li>
<li class="alt"><span>};</span></li>
<li class="alt"><span><span class="keyword">template</span><span>&lt;&gt;</span></span></li>
<li><span><span class="keyword">struct</span><span> both_random_helper&lt;</span></span></li>
<li class="alt"><span> std::random_access_iterator_tag,</span></li>
<li><span> std::random_access_iterator_tag&gt;{</span></li>
<li class="alt"><span> <span class="keyword">typedef</span><span> std::random_access_iterator_tag Iter_cat;</span></span></li>
<li><span>};</span></li>
<li><span><span class="comment">// 用于存放一对迭代器</span></span></li>
<li class="alt"><span><span class="keyword">template</span><span>&lt;</span><span class="keyword">class</span><span> _InIt, </span><span class="keyword">class</span><span> _OutIt&gt;</span></span></li>
<li><span><span class="keyword">struct</span><span> Iter_pair{</span></span></li>
<li class="alt"><span> _InIt m_in;</span></li>
<li><span> _OutIt m_out;</span></li>
<li class="alt"><span> Iter_pair(_InIt _in, _OutIt _out)</span></li>
<li><span> :m_in(_in),m_out(_out){}</span></li>
<li class="alt"><span> <span class="comment">//支持blocked_range拆分</span></span></li>
<li><span> Iter_pair operator+(<span class="datatypes">size_t</span><span> off) </span><span class="keyword">const</span></span></li>
<li class="alt"><span> {</span></li>
<li><span> <span class="keyword">return</span><span> Iter_pair(m_in+off, m_out+off);</span></span></li>
<li class="alt"><span> }</span></li>
<li class="alt"><span> <span class="datatypes">size_t</span><span> operator-(Iter_pair rhs) </span><span class="keyword">const</span></span></li>
<li><span> {</span></li>
<li class="alt"><span> <span class="keyword">return</span><span> m_in-rhs.m_in;</span></span></li>
<li><span> }</span></li>
<li><span> <span class="datatypes">bool</span><span> operator&lt;(Iter_pair rhs) </span><span class="keyword">const</span></span></li>
<li class="alt"><span> {</span></li>
<li><span> <span class="keyword">return</span><span> m_in&lt;rhs.m_in;</span></span></li>
<li class="alt"><span> }</span></li>
<li><span>};</span></li>
<li><span><span class="comment">// 随机存取迭代器版本</span></span></li>
<li class="alt"><span><span class="keyword">template</span><span>&lt;</span><span class="keyword">class</span><span> _InIt, </span><span class="keyword">class</span><span> _OutIt, </span><span class="keyword">class</span><span> _Fn1&gt;</span></span></li>
<li><span><span class="keyword">struct</span><span> op_parallel_transform{</span></span></li>
<li class="alt"><span> op_parallel_transform(_Fn1 _Func)</span></li>
<li><span> :m_Func(_Func){}</span></li>
<li class="alt"><span> <span class="keyword">void</span><span> operator()(</span><span class="keyword">const</span><span> tbb::blocked_range&lt;Iter_pair&lt;_InIt,_OutIt&gt; &gt; &amp;r) </span><span class="keyword">const</span></span></li>
<li><span> {</span></li>
<li class="alt"><span> std::transform(r.begin().m_in, r.end().m_in, r.begin().m_out, m_Func);</span></li>
<li><span> }</span></li>
<li class="alt"><span><span class="keyword">private</span><span>:</span></span></li>
<li><span> _Fn1 m_Func;</span></li>
<li class="alt"><span>};</span></li>
<li class="alt"><span><span class="keyword">template</span><span>&lt;</span><span class="keyword">class</span><span> _InIt, </span><span class="keyword">class</span><span> _OutIt, </span><span class="keyword">class</span><span> _Fn1&gt;</span></span></li>
<li><span>_OutIt _parallel_transform(_InIt _First, _InIt _Last, _OutIt _Dest, _Fn1 _Func, std::random_access_iterator_tag)</span></li>
<li class="alt"><span>{</span></li>
<li><span> <span class="comment">// 使用parallel_for来处理</span></span></li>
<li class="alt"><span> <span class="keyword">typedef</span><span> </span><span class="keyword">typename</span><span> Iter_pair&lt;_InIt,_OutIt&gt; iter_pair_type;</span></span></li>
<li><span> _OutIt LastDest = _Dest + (_Last - _First);</span></li>
<li class="alt"><span> iter_pair_type begin(_First, _Dest);</span></li>
<li><span> iter_pair_type end(_Last, LastDest);</span></li>
<li class="alt"><span> tbb::blocked_range&lt;iter_pair_type&gt; x(begin, end);</span></li>
<li><span> tbb::parallel_for(x, op_parallel_transform&lt;_InIt,_OutIt,_Fn1&gt;(_Func), tbb::auto_partitioner());</span></li>
<li class="alt"><span> <span class="keyword">return</span><span> LastDest;</span></span></li>
<li><span>}</span></li>
<li><span><span class="comment">//-----------------顺序存取迭代器版本-------------------------------------</span></span></li>
<li class="alt"><span><span class="keyword">template</span><span>&lt;</span><span class="keyword">class</span><span> _InIt&gt;</span></span></li>
<li><span><span class="keyword">struct</span><span> filter_in : tbb::filter{</span></span></li>
<li class="alt"><span> filter_in(_InIt _First, _InIt _Last)</span></li>
<li><span> :tbb::filter(<span class="keyword">true</span><span>),m_First(_First), m_Last(_Last){}</span></span></li>
<li class="alt"><span> <span class="keyword">void</span><span>* operator()(</span><span class="keyword">void</span><span>*)</span></span></li>
<li><span> {</span></li>
<li class="alt"><span> <span class="keyword">if</span><span>(m_First==m_Last) </span><span class="keyword">return</span><span> NULL;</span></span></li>
<li class="alt"><span> <span class="keyword">void</span><span>* p = &amp;(*m_First);</span></span></li>
<li><span> ++m_First;</span></li>
<li class="alt"><span> <span class="keyword">return</span><span> p;</span></span></li>
<li><span> }</span></li>
<li class="alt"><span><span class="keyword">private</span><span>:</span></span></li>
<li><span> _InIt m_First, m_Last;</span></li>
<li class="alt"><span>};</span></li>
<li class="alt"><span><span class="keyword">template</span><span>&lt;</span><span class="keyword">class</span><span> _Fn1&gt;</span></span></li>
<li><span><span class="keyword">struct</span><span> filter_process : tbb::filter{</span></span></li>
<li class="alt"><span> <span class="keyword">typedef</span><span> </span><span class="keyword">typename</span><span> _Fn1::result_type r_type;</span></span></li>
<li><span> <span class="keyword">typedef</span><span> </span><span class="keyword">typename</span><span> _Fn1::argument_type a_type;</span></span></li>
<li><span> filter_process(_Fn1 _Func)</span></li>
<li class="alt"><span> :tbb::filter(<span class="keyword">false</span><span>),m_Func(_Func){}</span></span></li>
<li><span> <span class="keyword">void</span><span>* operator()(</span><span class="keyword">void</span><span>* data)</span></span></li>
<li class="alt"><span> {</span></li>
<li><span> a_type &amp;at = *(a_type*)data;</span></li>
<li class="alt"><span> m_r = m_Func( at );</span></li>
<li><span> <span class="keyword">return</span><span> &amp;m_r;</span></span></li>
<li class="alt"><span> }</span></li>
<li><span><span class="keyword">private</span><span>:</span></span></li>
<li class="alt"><span> _Fn1 m_Func;</span></li>
<li><span> r_type m_r;</span></li>
<li class="alt"><span>};</span></li>
<li class="alt"><span><span class="keyword">template</span><span>&lt;</span><span class="keyword">class</span><span> _OutIt, </span><span class="keyword">class</span><span> _DataType&gt;</span></span></li>
<li><span><span class="keyword">struct</span><span> filter_out : tbb::filter{</span></span></li>
<li class="alt"><span> filter_out(_OutIt _Dest)</span></li>
<li><span> :tbb::filter(<span class="keyword">true</span><span>),m_Dest(_Dest){}</span></span></li>
<li class="alt"><span> <span class="keyword">void</span><span>* operator()(</span><span class="keyword">void</span><span>* data)</span></span></li>
<li><span> {</span></li>
<li class="alt"><span> _DataType *p = (_DataType*) data;</span></li>
<li><span> *m_Dest = *p;</span></li>
<li class="alt"><span> ++m_Dest;</span></li>
<li><span> <span class="keyword">return</span><span> NULL;</span></span></li>
<li class="alt"><span> }</span></li>
<li><span><span class="keyword">private</span><span>:</span></span></li>
<li class="alt"><span> _OutIt m_Dest;</span></li>
<li><span>};</span></li>
<li><span><span class="keyword">template</span><span>&lt;</span><span class="keyword">class</span><span> _InIt, </span><span class="keyword">class</span><span> _OutIt, </span><span class="keyword">class</span><span> _Fn1&gt;</span></span></li>
<li class="alt"><span>_OutIt _parallel_transform(_InIt _First, _InIt _Last, _OutIt _Dest, _Fn1 _Func, std::forward_iterator_tag)</span></li>
<li><span>{</span></li>
<li class="alt"><span> <span class="comment">// 使用管线pipeline来处理</span></span></li>
<li><span> tbb::pipeline pipeline;</span></li>
<li class="alt"><span> filter_in&lt;_InIt&gt; f1(_First, _Last);</span></li>
<li><span> filter_process&lt;_Fn1&gt; f2(_Func);</span></li>
<li class="alt"><span> filter_out&lt;_OutIt, _Fn1::result_type&gt; f3(_Dest);</span></li>
<li><span> pipeline.add_filter(f1);</span></li>
<li class="alt"><span> pipeline.add_filter(f2);</span></li>
<li><span> pipeline.add_filter(f3);</span></li>
<li class="alt"><span> pipeline.run(3);</span></li>
<li><span> <span class="keyword">return</span><span> _Dest;</span></span></li>
<li class="alt"><span>}</span></li>
<li class="alt"><span><span class="comment">//----------------------parallel_transform----------------------------</span></span></li>
<li><span><span class="keyword">template</span><span>&lt;</span><span class="keyword">class</span><span> _InIt, </span><span class="keyword">class</span><span> _OutIt, </span><span class="keyword">class</span><span> _Fn1&gt;</span></span></li>
<li class="alt"><span><span class="keyword">inline</span></span></li>
<li><span>_OutIt parallel_transform(_InIt _First, _InIt _Last, _OutIt _Dest, _Fn1 _Func)</span></li>
<li class="alt"><span>{</span></li>
<li><span> <span class="keyword">typedef</span><span> </span><span class="keyword">typename</span><span> std::iterator_traits&lt;_InIt&gt;::iterator_category cat1;</span></span></li>
<li class="alt"><span> <span class="keyword">typedef</span><span> </span><span class="keyword">typename</span><span> std::iterator_traits&lt;_OutIt&gt;::iterator_category cat2;</span></span></li>
<li><span> <span class="keyword">return</span><span> _parallel_transform(_First, _Last, _Dest, _Func, both_random_helper&lt;cat1,cat2&gt;::Iter_cat());</span></span></li>
<li class="alt"><span>}</span></li>
<li class="alt"><span><span class="comment">// 测试代码</span></span></li>
<li><span><span class="keyword">struct</span><span> SinFunctor</span></span></li>
<li class="alt"><span> :std::unary_function&lt;<span class="datatypes">double</span><span>, </span><span class="datatypes">double</span><span>&gt;{</span></span></li>
<li><span> <span class="datatypes">double</span><span> operator()(</span><span class="datatypes">double</span><span> &amp;d) </span><span class="keyword">const</span></span></li>
<li class="alt"><span> {</span></li>
<li><span> <span class="comment">// 高强度运算</span></span></li>
<li class="alt"><span> <span class="datatypes">double</span><span> sum = 0;</span></span></li>
<li><span> <span class="keyword">for</span><span>(</span><span class="datatypes">int</span><span> i=0; i&lt;10000; i++)  sum += sin(i*d);</span></span></li>
<li class="alt"><span> <span class="keyword">return</span><span> sum;</span></span></li>
<li><span> }</span></li>
<li class="alt"><span>};</span></li>
<li class="alt"><span><span class="datatypes">int</span><span> main()</span></span></li>
<li><span>{</span></li>
<li class="alt"><span> <span class="comment">// 随机存取迭代</span></span></li>
<li><span> std::vector&lt;<span class="datatypes">double</span><span>&gt; a(10000,1.5);</span></span></li>
<li class="alt"><span> <span class="comment">// 顺序存取迭代</span></span></li>
<li><span> std::list&lt;<span class="datatypes">double</span><span>&gt;   b(10000,1.5);</span></span></li>
<li><span> tbb::task_scheduler_init init;</span></li>
<li><span> tbb::tick_count t0,t1;</span></li>
<li><span> t0 = tbb::tick_count::now();</span></li>
<li class="alt"><span> parallel_transform(a.begin(), a.end(), a.begin(), SinFunctor());</span></li>
<li><span> t1 = tbb::tick_count::now();</span></li>
<li class="alt"><span> std::cout &lt;&lt; <span class="string">"并行（随机迭代）"</span><span> &lt;&lt; (t1 - t0).seconds() &lt;&lt; std::endl;</span></span></li>
<li><span> </span></li>
<li class="alt"><span> t0 = tbb::tick_count::now();</span></li>
<li><span> std::transform(a.begin(), a.end(), a.begin(), SinFunctor());</span></li>
<li class="alt"><span> t1 = tbb::tick_count::now();</span></li>
<li><span> std::cout &lt;&lt; <span class="string">"原版（随机迭代）"</span><span> &lt;&lt; (t1 - t0).seconds() &lt;&lt; std::endl;</span></span></li>
<li><span> t0 = tbb::tick_count::now();</span></li>
<li class="alt"><span> parallel_transform(b.begin(), b.end(), b.begin(), SinFunctor());</span></li>
<li><span> t1 = tbb::tick_count::now();</span></li>
<li class="alt"><span> std::cout &lt;&lt; <span class="string">"并行（顺序迭代）"</span><span> &lt;&lt; (t1 - t0).seconds() &lt;&lt; std::endl;</span></span></li>
<li class="alt"><span> t0 = tbb::tick_count::now();</span></li>
<li><span> std::transform(b.begin(), b.end(), b.begin(), SinFunctor());</span></li>
<li class="alt"><span> t1 = tbb::tick_count::now();</span></li>
<li><span> std::cout &lt;&lt; <span class="string">"原版（顺序迭代）"</span><span>&lt;&lt; (t1 - t0).seconds() &lt;&lt; std::endl;</span></span></li>
<li class="alt"><span> </span></li>
<li><span> std::cin.get();</span></li>
<li class="alt"><span> <span class="keyword">return</span><span> 0;</span></span></li>
<li><span>}</span></li>
</ol>
</div>
</div>
<p>在我的双核Centrino电脑上测试结果如下：</p>
<p>并行（随机迭代）3.17299 原版（随机迭代）5.41531 并行（顺序迭代）3.13054 原版（顺序迭代）5.33182</p>
<p>在顺序存取迭代器版本的_parallel_transform中，因为迭代器不能随意跳转，所以使用了tbb::pipeline加三个filter分别执行顺序读取，处理和写入。其中的处理是可以并行处理的。从上面的结果可以看出，pipeline的性能甚至不亚于parallel_for循环。关于 pipeline的使用说明，请参考文章：<a href="http://www.cppprog.com/2009/0325/92_4.html"><span style="color: #0000ff;">TBB流水线</span></a><br />
这里写的parallel_transform可以直接替换大家原有代码中的std::transform，当然如果有兴趣的话完全可以把标准库中的算法全用TBB改写成并行算法。不过要注意的一点是并不是任何地方都适合使用并行运算的，象这个例子中测试用的处理算子是“<span style="color: #0000ff;">for(int i=0; i&lt;10000; i++)  sum += sin(i*d);</span>”这样的需要耗时较长的运算，如果把它改成“<span style="color: #0000ff;">return sin(d);</span>”。那么考虑到线程调度以及TBB的任务调度，并行算法的效率可能还不如串行算法。</p>
<p>TBB库可以从这里下载：<a href="http://www.threadingbuildingblocks.org/download.php"><span style="color: #336699;">http://www.threadingbuildingblocks.org/download.php</span></a><br />
另外再推荐几篇TBB入门文章：<br />
<a href="http://www.cppprog.com/2009/0325/92.html"><span style="color: #336699;">Intel Threading Building Blocks 之 并行循环</span></a><br />
<a href="http://www.cppprog.com/2009/0326/93.html"><span style="color: #336699;">Intel Threading Building Blocks 之 并发容器</span></a><br />
<a href="http://www.cppprog.com/2009/0401/96.html"><span style="color: #336699;">Intel Threading Building Blocks 基于任务编程</span></a></p>
<p>相信度过了自己的20岁生日之后的C++，在多核时候将再创辉煌！</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/zh-cn/blogs/2009/05/04/c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

