<?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; Zhouweiming 周伟明</title>
	<atom:link href="http://software.intel.com/zh-cn/blogs/author/zhouweiming/feed/" rel="self" type="application/rss+xml" />
	<link>http://software.intel.com/zh-cn/blogs</link>
	<description></description>
	<lastBuildDate>Mon, 28 May 2012 14:23:20 +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>OpenMP编程的数据竞争问题</title>
		<link>http://software.intel.com/zh-cn/blogs/2009/12/28/openmp-3/</link>
		<comments>http://software.intel.com/zh-cn/blogs/2009/12/28/openmp-3/#comments</comments>
		<pubDate>Mon, 28 Dec 2009 03:09:02 +0000</pubDate>
		<dc:creator>Zhouweiming 周伟明</dc:creator>
				<category><![CDATA[博客征文专栏]]></category>
		<category><![CDATA[并行计算]]></category>

		<guid isPermaLink="false">http://software.intel.com/zh-cn/blogs/2009/12/28/openmp-3/</guid>
		<description><![CDATA[OpenMP编程的数据竞争问题 使用OpenMP编程时，通常都是将函数内的某段代码并行化执行，但是，对于在函数内声明的变量，很容易被多个线程同时读写访问，这将导致数据竞争问题。 不妨先看一个代码例子： 找出下面代码中的问题 template &#60;class T&#62; void Parallel_Matrix_Sub(T *a, int row_a, int col_a, int as,  T *b, int bs, T *c, int cs) { int i, j; int nCore = omp_get_num_procs(); #pragma omp parallel for num_threads(nCore) for ( i = 0; i &#60; row_a; i++ ) { int row_i_a = i * as; int [...]]]></description>
			<content:encoded><![CDATA[<p><strong>OpenMP</strong><strong>编程的数据竞争问题</strong><strong> </strong></p>
<p>使用OpenMP编程时，通常都是将函数内的某段代码并行化执行，但是，对于在函数内声明的变量，很容易被多个线程同时读写访问，这将导致数据竞争问题。</p>
<p>不妨先看一个代码例子：</p>
<p><strong>找出下面代码中的问题 </strong></p>
<p>template &lt;class T&gt;</p>
<p>void Parallel_Matrix_Sub(T *a, int row_a, int col_a, int as,  T *b, int bs, T *c, int cs)</p>
<p>{</p>
<p>int i, j;</p>
<p>int nCore = omp_get_num_procs();</p>
<p>#pragma omp parallel for num_threads(nCore)</p>
<p>for ( i = 0; i &lt; row_a; i++ )</p>
<p>{</p>
<p>int row_i_a = i * as;</p>
<p>int row_i_b = i * bs;</p>
<p>int row_i_c = i * cs;</p>
<p>for ( j = 0; j &lt; col_a; j++ )</p>
<p>{</p>
<p>//c[i][j] = a[i][j] - b[i][j]</p>
<p>c[row_i_c + j] = a[row_i_a + j] - b[row_i_b + j];</p>
<p>}</p>
<p>}</p>
<p>}</p>
<p>稍有经验的人就可以发现，上面代码中，j变量声明在OpenMP语句块的外面，因此，对各个线程来说，它是共享变量，OpenMP创建的多个线程都会访问j。内层循环中的j++可能会被多个线程同时执行，将导致程序运行出现无法预测的错误。改正后的代码如下：</p>
<p>template &lt;class T&gt;</p>
<p>void Parallel_Matrix_Sub(T *a, int row_a, int col_a, int as,  T *b, int bs, T *c, int cs)</p>
<p>{</p>
<p>int i;</p>
<p><strong> const int nCore = omp_get_num_procs(); </strong></p>
<p>#pragma omp parallel for num_threads(nCore)</p>
<p>for ( i = 0; i &lt; row_a; i++ )</p>
<p>{</p>
<p><strong> int   j; </strong></p>
<p>int row_i_a = i * as;</p>
<p>int row_i_b = i * bs;</p>
<p>int row_i_c = i * cs;</p>
<p>for ( j = 0; j &lt; col_a; j++ )</p>
<p>{</p>
<p>//c[i][j] = a[i][j] - b[i][j]</p>
<p>c[row_i_c + j] = a[row_i_a + j] - b[row_i_b + j];</p>
<p>}</p>
<p>}</p>
<p>}</p>
<p>注意上面的代码中的加粗两行，变量j改为在内层循环内声明，这样创建线程时，变量j为每个线程的局部变量，不存在数据竞争问题。</p>
<p>对于<strong>const int nCore = omp_get_num_procs(); </strong>这行，将变量nCore声明为</p>
<p>const类型后，后面的代码就无法对其进行写操作，可以避免线程内的代码对线程外的变量进行写操作，避免数据竞争问题。</p>
<p>根据上面的实例修改情况，可以归纳出两条避免OpenMP出现数据竞争的建议：</p>
<p>1．  尽量在并行循环内部申明局部变量</p>
<p>2．  对于并行循环外面的变量，尽量使用const类型，以保证在并行循环内不会发生写操作。对于没有使用const的变量，表明需要进行写操作，可以在检视代码时重点检视这些未使用const的变量是否用了锁或原子操作来进行保护。</p>
<p>参考材料： <a href="http://blog.csdn.net/drzhouweiming/archive/2009/04/20/4093624.aspx">OpenMP编程指南</a></p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/zh-cn/blogs/2009/12/28/openmp-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>多核程序调试与测试(1)</title>
		<link>http://software.intel.com/zh-cn/blogs/2009/12/28/400002942/</link>
		<comments>http://software.intel.com/zh-cn/blogs/2009/12/28/400002942/#comments</comments>
		<pubDate>Mon, 28 Dec 2009 03:08:37 +0000</pubDate>
		<dc:creator>Zhouweiming 周伟明</dc:creator>
				<category><![CDATA[博客征文专栏]]></category>
		<category><![CDATA[并行计算]]></category>

		<guid isPermaLink="false">http://software.intel.com/zh-cn/blogs/2009/12/28/400002942/</guid>
		<description><![CDATA[多核程序调试与测试 注：本文主要根据今年到某企业讲课的胶片整理而成，因为是胶片，内容会显得比较精简，不到之处还请海涵。 多核程序的调试与测试历来是世界性难题，岂止为止没有发现能够对付它的银弹。这是因为多核程序与单核程序有着很大的不同，单核程序通常是一些内存访问、资源泄漏、计算错误（如差1）等。多核程序中，不仅会遇到单核程序中所遇到的所有问题，还会遇到许多新的问题和陷阱。 多核程序常见问题与陷阱 多核常见问题和陷阱如下： 1）数据竞争 2）死锁 3）数据操作时序 4）活锁 5）原子操作 6）资源回收 7）优先级翻转 8）线程挂起或死亡 9）线程重启 下面就来探讨一下这些问题和陷阱 数据竞争 常见的数据竞争问题有以下几种： 1）OpenMP中的数据竞争 2）原子操作中的数据竞争 3）通常多线程环境中的数据竞争 一般来说，数据竞争是一种非常难以发现和调试的问题，因为多个线程同时操作某个变量的频率本来就非常低，这使得问题需要重复非常多次才能出现一次，给测试带来了难度。 同时，如果要对数据竞争问题进行定位，难度就更大了，如果进行单步执行，问题很可能根本就不会出现。 对付数据竞争最有效的方法就是使用人工进行代码静态审查，找一些对多线程编程富有经验的人，对含有共享数据操作的模块进行代码检视。 另外一个方法就是借助工具，有一些专门的工具可以用来检查某些类型的数据竞争问题，比如Intel线程检测器工具可以识别数据竞争、死锁、等问题。]]></description>
			<content:encoded><![CDATA[<h1>多核程序调试与测试</h1>
<p><em>注：本文主要根据今年到某企业讲课的胶片整理而成，因为是胶片，内容会显得比较精简，不到之处还请海涵。</em></p>
<p>多核程序的调试与测试历来是世界性难题，岂止为止没有发现能够对付它的银弹。这是因为多核程序与单核程序有着很大的不同，单核程序通常是一些内存访问、资源泄漏、计算错误（如差1）等。多核程序中，不仅会遇到单核程序中所遇到的所有问题，还会遇到许多新的问题和陷阱。</p>
<h2>多核程序常见问题与陷阱</h2>
<p>多核常见问题和陷阱如下：</p>
<p>1）数据竞争</p>
<p>2）死锁</p>
<p>3）数据操作时序</p>
<p>4）活锁</p>
<p>5）原子操作</p>
<p>6）资源回收</p>
<p>7）优先级翻转</p>
<p>8）线程挂起或死亡</p>
<p>9）线程重启</p>
<p>下面就来探讨一下这些问题和陷阱</p>
<p><strong>数据竞争</strong><strong></strong></p>
<p>常见的数据竞争问题有以下几种：</p>
<p>1）OpenMP中的数据竞争</p>
<p>2）原子操作中的数据竞争</p>
<p>3）通常多线程环境中的数据竞争</p>
<p>一般来说，数据竞争是一种非常难以发现和调试的问题，因为多个线程同时操作某个变量的频率本来就非常低，这使得问题需要重复非常多次才能出现一次，给测试带来了难度。</p>
<p>同时，如果要对数据竞争问题进行定位，难度就更大了，如果进行单步执行，问题很可能根本就不会出现。</p>
<p>对付数据竞争最有效的方法就是使用人工进行代码静态审查，找一些对多线程编程富有经验的人，对含有共享数据操作的模块进行代码检视。</p>
<p>另外一个方法就是借助工具，有一些专门的工具可以用来检查某些类型的数据竞争问题，比如Intel线程检测器工具可以识别数据竞争、死锁、等问题。</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/zh-cn/blogs/2009/12/28/400002942/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>多核程序调试与测试(3)</title>
		<link>http://software.intel.com/zh-cn/blogs/2009/12/28/400002947/</link>
		<comments>http://software.intel.com/zh-cn/blogs/2009/12/28/400002947/#comments</comments>
		<pubDate>Mon, 28 Dec 2009 03:07:48 +0000</pubDate>
		<dc:creator>Zhouweiming 周伟明</dc:creator>
				<category><![CDATA[博客征文专栏]]></category>
		<category><![CDATA[并行计算]]></category>

		<guid isPermaLink="false">http://software.intel.com/zh-cn/blogs/2009/12/28/400002947/</guid>
		<description><![CDATA[多核程序的测试 测试方法和步骤 1）先将程序编译成串行版本 2）对串行版本进行详尽的测试，确保没有问题 3）再编译成并行版本 4）对并行版本进行测试 死锁测试 死锁问题一般可以通过设计消除 – 将Lock() Unlock()操作改成 CScopedLock类调用 –  避免嵌套锁 – 检查是否有活锁问题 – 采用类似内存测试的方法进行测试 数据竞争测试 在核数较多的机器上进行测试 代码中不要插入测试和调试代码 如果用了sleep等延时操作，可以将其注释掉进行测试 代码静态检查 人工进行代码静态检查是必须的 重点检查数据竞争和数据操作时序 测试用例设计 基于阻塞情况而设计用例 – 比如在数据为空或为满情况下是否会出现阻塞现象 基于数据状态而设计用例 – 比如设计一些可能出现的中间数据状态，作为输入进行测试 测试用例设计 设计模拟线程切换的用例 – 监控共享变量的读写 – 让一个线程进行上锁状态然后挂起，其他线程继续运行，看是否会操作到共享变量 问题定位 在实践中发现，如果采用单元测试进行问题定位，效果通常较好，所以一定要做单元测试啊！采用其他手段定位则麻烦许多，其他常见的定位手段如下： 1）采用数据断点进行定位 2）分段调试进行定位 3）暴力调试进行定位 顺便说一下，对于多线程调试与测试，通常需要较好的工具来支持，对于某些用工具几分钟就能解决的问题，不使用工具或许会需要几天甚至被卡住而做不下去。]]></description>
			<content:encoded><![CDATA[<h2>多核程序的测试</h2>
<p><strong>测试方法和步骤</strong><strong> </strong></p>
<p>1）先将程序编译成串行版本</p>
<p>2）对串行版本进行详尽的测试，确保没有问题</p>
<p>3）再编译成并行版本</p>
<p>4）对并行版本进行测试</p>
<p><strong>死锁测试</strong><strong> </strong></p>
<p>死锁问题一般可以通过设计消除</p>
<p>– 将Lock() Unlock()操作改成 CScopedLock类调用</p>
<p>–  避免嵌套锁</p>
<p>– 检查是否有活锁问题</p>
<p>– 采用类似内存测试的方法进行测试</p>
<p><strong>数据竞争测试</strong><strong></strong></p>
<p>在核数较多的机器上进行测试</p>
<p>代码中不要插入测试和调试代码</p>
<p>如果用了sleep等延时操作，可以将其注释掉进行测试</p>
<p><strong>代码静态检查</strong><strong></strong></p>
<p>人工进行代码静态检查是必须的</p>
<p>重点检查数据竞争和数据操作时序</p>
<p><strong>测试用例设计</strong><strong></strong></p>
<p>基于阻塞情况而设计用例</p>
<p>– 比如在数据为空或为满情况下是否会出现阻塞现象</p>
<p>基于数据状态而设计用例</p>
<p>– 比如设计一些可能出现的中间数据状态，作为输入进行测试</p>
<p><strong>测试用例设计</strong><strong></strong></p>
<p>设计模拟线程切换的用例</p>
<p>– 监控共享变量的读写</p>
<p>– 让一个线程进行上锁状态然后挂起，其他线程继续运行，看是否会操作到共享变量</p>
<p><strong>问题定位</strong><strong></strong></p>
<p>在实践中发现，如果采用单元测试进行问题定位，效果通常较好，所以一定要做单元测试啊！采用其他手段定位则麻烦许多，其他常见的定位手段如下：</p>
<p>1）采用数据断点进行定位</p>
<p>2）分段调试进行定位</p>
<p>3）暴力调试进行定位</p>
<p>顺便说一下，对于多线程调试与测试，通常需要较好的工具来支持，对于某些用工具几分钟就能解决的问题，不使用工具或许会需要几天甚至被卡住而做不下去。</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/zh-cn/blogs/2009/12/28/400002947/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>多核程序调试与测试(2)</title>
		<link>http://software.intel.com/zh-cn/blogs/2009/12/19/400002945/</link>
		<comments>http://software.intel.com/zh-cn/blogs/2009/12/19/400002945/#comments</comments>
		<pubDate>Sat, 19 Dec 2009 13:39:22 +0000</pubDate>
		<dc:creator>Zhouweiming 周伟明</dc:creator>
				<category><![CDATA[博客征文专栏]]></category>
		<category><![CDATA[并行计算]]></category>

		<guid isPermaLink="false">http://software.intel.com/zh-cn/blogs/2009/12/19/400002945/</guid>
		<description><![CDATA[死锁 导致死锁的因素通常有以下几种： 1）忘记解锁 2）嵌套锁顺序错误 3）递归锁 死锁的问题很容易解决，忘记死锁可以通过使用CScopedLock类，利用类的析构函数自动释放锁，程序中尽量避免使用嵌套锁等，一般来说，嵌套锁都可以改写成非嵌套的锁。 数据操作时序 数据操作时序和数据竞争不一样，它发生于两次加锁解锁之间进行了任务切换。如果第2次加锁解锁的共享变量依赖于第1次加锁解锁的共享变量，两次之间切换任务时，修改了第1次的共享变量的值，将导致第2次访问的共享变量的值的变化，从而产生一些不可预知的问题。 数据操作时序问题的出现是随机性的，有些问题出现概率很小，很难定位 一般使用代码静态分析方法来发现这类问题 使用原子操作时最容易犯这个问题，这也是无锁编程的困难所在 活锁 多个线程A、B、C都在等待某一个锁，线程A释放锁，线程B获得锁，这时线程A又重新等待锁，线程B释放后，线程A又获得锁，如此循环下去，将导致线程C永远得不到锁。 这种锁一直被某几个线程持有，使得某个线程一直等不到锁的情况叫做“活锁”。 活锁问题通常与操作系统的线程调度策略有关，对于现代操作系统来说，同优先级线程通常采用轮循调度，一般不会发生活锁问题，但是对于不同优先级的线程，通常采用抢占式调度，则有可能发生活锁问题。 原子操作 现在的多核机器通常都支持原子操作，原子操作通常比锁的效率高（注：也有用原子操作实现的锁），原子操作一个最大的优势就是不会出现死锁，另外使用原子操作操作的变量，读取该变量时和读取普通变量是一样的，即使锁做得和原子操作一样快，原子操作也可以省去一半的操作开销。 原子操作使用的难度要比锁高，因此有以下注意事项： 1）原子操作极易引起数据竞争和数据操作时序问题 2）通过返回值获取变量修改后的值 3）不要轻易对指针使用原子操作 资源回收 多线程环境中的资源回收和单线程环境不同，单线程环境的回收资源通常是指资源泄漏问题，多线程环境的资源回收是指在回收了某个资源后，还有一些没有退出的常驻线程会继续访问这些已被释放了的资源。 保证安全回收资源的两点建议： 1）  确保资源回收前，其他线程都不会再访问这个资源 2）使用多线程退出算法来保证资源被回收前，让需要访问这个资源的线程全部退出。 线程挂起或死亡 在使用了锁的线程中，线程挂起通常是非常危险的问题，因为它有可能导致线程持有的锁没有释放，从而让其他线程等不到锁，一直等待下去。 线程重启 有些应用中，需要在不退出进程的情况下将线程重启，将线程重启也是一种难度较高的动作，因为首先需要将原线程退出，再将线程运行起来，线程重启时，如何确保资源被安全释放或安全保存，如何保证重启时，程序数据的安全？对于大型软件来说，这些问题都是比较棘手的问题。因此，除非有特殊需要，一般不要设计线程可以重启的应用。 要做到让线程重启的安全，以下几点供参考： 1）使用多线程退出算法让线程自然退出 2）释放线程私有资源 3）释放线程持有的锁 至此，将多线程编程常见问题和陷阱简要地过了一遍，下面接着谈谈多核程序测试方面。]]></description>
			<content:encoded><![CDATA[<p><strong>死锁</strong><strong></strong></p>
<p>导致死锁的因素通常有以下几种：</p>
<p>1）忘记解锁</p>
<p>2）嵌套锁顺序错误</p>
<p>3）递归锁</p>
<p>死锁的问题很容易解决，忘记死锁可以通过使用CScopedLock类，利用类的析构函数自动释放锁，程序中尽量避免使用嵌套锁等，一般来说，嵌套锁都可以改写成非嵌套的锁。</p>
<p><strong>数据操作时序</strong><strong></strong></p>
<p>数据操作时序和数据竞争不一样，它发生于两次加锁解锁之间进行了任务切换。如果第2次加锁解锁的共享变量依赖于第1次加锁解锁的共享变量，两次之间切换任务时，修改了第1次的共享变量的值，将导致第2次访问的共享变量的值的变化，从而产生一些不可预知的问题。</p>
<p>数据操作时序问题的出现是随机性的，有些问题出现概率很小，很难定位</p>
<p>一般使用代码静态分析方法来发现这类问题</p>
<p>使用原子操作时最容易犯这个问题，这也是无锁编程的困难所在</p>
<p><strong>活锁</strong><strong></strong></p>
<p>多个线程A、B、C都在等待某一个锁，线程A释放锁，线程B获得锁，这时线程A又重新等待锁，线程B释放后，线程A又获得锁，如此循环下去，将导致线程C永远得不到锁。</p>
<p>这种锁一直被某几个线程持有，使得某个线程一直等不到锁的情况叫做“活锁”。</p>
<p>活锁问题通常与操作系统的线程调度策略有关，对于现代操作系统来说，同优先级线程通常采用轮循调度，一般不会发生活锁问题，但是对于不同优先级的线程，通常采用抢占式调度，则有可能发生活锁问题。</p>
<p><strong>原子操作</strong><strong></strong></p>
<p>现在的多核机器通常都支持原子操作，原子操作通常比锁的效率高（注：也有用原子操作实现的锁），原子操作一个最大的优势就是不会出现死锁，另外使用原子操作操作的变量，读取该变量时和读取普通变量是一样的，即使锁做得和原子操作一样快，原子操作也可以省去一半的操作开销。</p>
<p>原子操作使用的难度要比锁高，因此有以下注意事项：</p>
<p>1）原子操作极易引起数据竞争和数据操作时序问题</p>
<p>2）通过返回值获取变量修改后的值</p>
<p>3）不要轻易对指针使用原子操作</p>
<p><strong>资源回收</strong><strong></strong></p>
<p>多线程环境中的资源回收和单线程环境不同，单线程环境的回收资源通常是指资源泄漏问题，多线程环境的资源回收是指在回收了某个资源后，还有一些没有退出的常驻线程会继续访问这些已被释放了的资源。</p>
<p>保证安全回收资源的两点建议：</p>
<p>1）  确保资源回收前，其他线程都不会再访问这个资源</p>
<p>2）使用多线程退出算法来保证资源被回收前，让需要访问这个资源的线程全部退出。</p>
<p><strong>线程挂起或死亡</strong><strong></strong></p>
<p>在使用了锁的线程中，线程挂起通常是非常危险的问题，因为它有可能导致线程持有的锁没有释放，从而让其他线程等不到锁，一直等待下去。</p>
<p><strong>线程重启</strong><strong></strong></p>
<p>有些应用中，需要在不退出进程的情况下将线程重启，将线程重启也是一种难度较高的动作，因为首先需要将原线程退出，再将线程运行起来，线程重启时，如何确保资源被安全释放或安全保存，如何保证重启时，程序数据的安全？对于大型软件来说，这些问题都是比较棘手的问题。因此，除非有特殊需要，一般不要设计线程可以重启的应用。</p>
<p>要做到让线程重启的安全，以下几点供参考：</p>
<p>1）使用多线程退出算法让线程自然退出</p>
<p>2）释放线程私有资源</p>
<p>3）释放线程持有的锁</p>
<p>至此，将多线程编程常见问题和陷阱简要地过了一遍，下面接着谈谈多核程序测试方面。</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/zh-cn/blogs/2009/12/19/400002945/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>多核动态任务调度的进一步探索(6)</title>
		<link>http://software.intel.com/zh-cn/blogs/2009/12/08/400002857/</link>
		<comments>http://software.intel.com/zh-cn/blogs/2009/12/08/400002857/#comments</comments>
		<pubDate>Tue, 08 Dec 2009 02:14:53 +0000</pubDate>
		<dc:creator>Zhouweiming 周伟明</dc:creator>
				<category><![CDATA[博客征文专栏]]></category>
		<category><![CDATA[并行计算]]></category>
		<category><![CDATA[开放源代码]]></category>

		<guid isPermaLink="false">http://software.intel.com/zh-cn/blogs/2009/12/08/400002857/</guid>
		<description><![CDATA[// 下面是CWaitTaskScheduler.cpp文件内容 /*  * Copyright (c) 2006-2008  * Author: Weiming Zhou  *  * Permission to use, copy, modify, distribute and sell this software  * and its documentation for any purpose is hereby granted without fee,  * provided that the above copyright notice appear in all copies and  * that both that copyright notice and this [...]]]></description>
			<content:encoded><![CDATA[<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="宋体;"><span style="small;"><span lang="EN-US">// </span><span style="minor-latin;">下面是</span><span lang="EN-US">CWaitTaskScheduler.cpp</span><span style="minor-latin;">文件内容</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">/*</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;"> </span>* Copyright (c) 2006-2008</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;"> </span>* Author: Weiming Zhou</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;"> </span>*</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;"> </span>* Permission to use, copy, modify, distribute and sell this software</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;"> </span>* and its documentation for any purpose is hereby granted without fee,</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;"> </span>* provided that the above copyright notice appear in all copies and</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;"> </span>* that both that copyright notice and this permission notice appear</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;"> </span>* in supporting documentation.<span style="yes;">  </span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;"> </span>*/</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">#ifdef</span><span style="yes;" lang="EN-US"> <span style="black;">_WIN32</span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">#define</span><span style="yes;" lang="EN-US"> <span style="black;">_WIN32_WINNT</span> 0x0401</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">#include</span><span style="yes;" lang="EN-US"> <span style="maroon;">&lt;windows.h&gt;</span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">#else</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">#include &lt;pthread.h&gt;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">#endif</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">#include</span><span style="yes;" lang="EN-US"> <span style="maroon;">"CapiGlobal.h"</span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">#include</span><span style="yes;" lang="EN-US"> <span style="maroon;">"CThreadPool.h"</span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">#include</span><span style="yes;" lang="EN-US"> <span style="maroon;">"CLocalQueue.h"</span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">#include</span><span style="yes;" lang="EN-US"> <span style="maroon;">"CStealQueue.h"</span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">#include</span><span style="yes;" lang="EN-US"> <span style="maroon;">"CDistributedQueue.h"</span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">#include</span><span style="yes;" lang="EN-US"> <span style="maroon;">"CWaitTaskScheduler.h"</span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">static</span><span style="yes;" lang="EN-US"> <span style="blue;">unsigned</span> <span style="blue;">int</span> <span style="black;">WINAPI</span> <span style="black;">WaitTaskScheduler_StartFunc</span>(<span style="blue;">void</span> *<span style="black;">pArgs</span>);</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">#define</span><span style="yes;" lang="EN-US"><span style="yes;">     </span><span style="black;">WAITTASK_QUEUE_SIZE</span><span style="yes;">     </span>128</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">CWaitTask</span><span style="yes;" lang="EN-US">::<span style="black;">CWaitTask</span>()</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="black;">pCount</span> = <span style="black;">NULL</span>;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">}</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">CTaskArray</span><span style="yes;" lang="EN-US">::<span style="black;">CTaskArray</span>(<span style="blue;">int</span> <span style="black;">nTaskArraySize</span>) </span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="black;">m_nTaskArraySize</span> = <span style="black;">nTaskArraySize</span>;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="black;">m_lTaskCount</span> = 0;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="black;">m_lCurTaskCount</span> = 0;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="black;">m_pTaskArray</span> = <span style="blue;">new</span> <span style="black;">CWaitTask</span>[<span style="black;">nTaskArraySize</span>];</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="black;">INT</span> <span style="black;">i</span>;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="blue;">for</span> ( <span style="black;">i</span> = 0; <span style="black;">i</span> &lt; <span style="black;">nTaskArraySize</span>; <span style="black;">i</span>++ )</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span>{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span><span style="black;">m_pTaskArray</span>[<span style="black;">i</span>].<span style="black;">pCount</span> = &amp;<span style="black;">m_lCurTaskCount</span>;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span>}</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">}</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">CTaskArray</span><span style="yes;" lang="EN-US">::~<span style="black;">CTaskArray</span>() </span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="blue;">delete</span> [] <span style="black;">m_pTaskArray</span>;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">}</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">INT</span><span style="yes;" lang="EN-US"> <span style="black;">CTaskArray</span>::<span style="black;">AddTask</span>(<span style="black;">THREADFUNC</span> <span style="black;">func</span>, <span style="blue;">void</span> *<span style="black;">pArg</span>)</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="blue;">if</span> ( <span style="black;">m_lTaskCount</span> &gt;= <span style="black;">m_nTaskArraySize</span> )</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span>{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span><span style="blue;">return</span> <span style="black;">CAPI_FAILED</span>;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span>}</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="black;">m_pTaskArray</span>[<span style="black;">m_lTaskCount</span>].<span style="black;">func</span> = <span style="black;">func</span>;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="black;">m_pTaskArray</span>[<span style="black;">m_lTaskCount</span>].<span style="black;">pArg</span> = <span style="black;">pArg</span>;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="black;">m_lTaskCount</span> += 1;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="black;">m_lCurTaskCount</span> = <span style="black;">m_lTaskCount</span>;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="blue;">return</span> <span style="black;">CAPI_SUCCESS</span>;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">}</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">LONG</span><span style="yes;" lang="EN-US"> <span style="black;">CTaskArray</span>::<span style="black;">GetTaskCount</span>()</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="blue;">return</span> <span style="black;">m_lTaskCount</span>;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">}</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">LONG</span><span style="yes;" lang="EN-US"> <span style="black;">CTaskArray</span>::<span style="black;">GetCurTaskCount</span>()</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="blue;">return</span> <span style="black;">m_lCurTaskCount</span>;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">}</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">/**<span style="1;">   </span></span><span style="yes;">等待任务调度的构造函数</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="宋体;"><span style="small;"><span style="yes;" lang="EN-US"><span style="1;">         </span>@return<span style="1;">  </span>constructor - </span><span style="yes;">无</span></span><span style="yes;" lang="EN-US"><span style="small;"><span style="1;">      </span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">*/</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">CWaitTaskScheduler</span><span style="yes;" lang="EN-US">::<span style="black;">CWaitTaskScheduler</span>()</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="black;">m_StartFunc</span> = <span style="black;">WaitTaskScheduler_StartFunc</span>;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="blue;">int</span> <span style="black;">n</span> = <span style="black;">m_ThreadPool</span>.<span style="black;">GetThreadCount</span>();</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="black;">m_DQueue</span>.<span style="black;">Create</span>(<span style="black;">WAITTASK_QUEUE_SIZE</span>, <span style="black;">n</span>, <span style="black;">WAITTASK_QUEUE_SIZE</span>, 0, </span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span><span style="black;">ThreadPool_GetThreadId</span>, &amp;<span style="black;">m_ThreadPool</span>);</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">}</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">/**<span style="1;">   </span></span><span style="yes;">等待任务调度的设置线程池的入口函数</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="宋体;"><span style="small;"><span style="yes;" lang="EN-US"><span style="1;">         </span>@param<span style="1;">  </span>THREADFUNC StartFunc - </span><span style="yes;">线程池的入口函数</span></span><span style="yes;" lang="EN-US"><span style="small;"><span style="1;">      </span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="宋体;"><span style="small;"><span style="yes;" lang="EN-US"><span style="1;">         </span>@return<span style="1;">  </span>void - </span><span style="yes;">无</span></span><span style="yes;" lang="EN-US"><span style="small;"><span style="1;">  </span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">*/</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">void</span><span style="yes;" lang="EN-US"> <span style="black;">CWaitTaskScheduler</span>::<span style="black;">SetStartFunc</span>(<span style="black;">THREADFUNC</span> <span style="black;">StartFunc</span>)</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="black;">m_StartFunc</span> = <span style="black;">StartFunc</span>;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">}</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">/**<span style="1;">   </span></span><span style="yes;">等待任务调度的获取任务函数</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="宋体;"><span style="small;"><span style="yes;" lang="EN-US"><span style="1;">         </span>@param<span style="1;">  </span>TASK &amp;Task - </span><span style="yes;">接收从分布式队列中获取的任务</span></span><span style="yes;" lang="EN-US"><span style="small;"><span style="1;"> </span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="宋体;"><span style="small;"><span style="yes;" lang="EN-US"><span style="1;">         </span>@return<span style="1;">  </span>int - </span><span style="yes;">成功返回</span><span style="yes;" lang="EN-US">CAPI_SUCCESS, </span><span style="yes;">失败返回</span></span><span style="yes;" lang="EN-US"><span style="small;">CAPI_FAILED.<span style="1;">     </span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">*/</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">int</span><span style="yes;" lang="EN-US"> <span style="black;">CWaitTaskScheduler</span>::<span style="black;">GetTask</span>(<span style="black;">CWaitTask</span> &amp;<span style="black;">Task</span>) </span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US"><span style="yes;">    </span>//</span><span style="yes;">先从本地队列获取任务</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US"><span style="yes;">    </span>//</span><span style="yes;">本地获取任务失败后从共享队列获取任务</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="blue;">return</span> <span style="black;">m_DQueue</span>.<span style="black;">DeQueue</span>(<span style="black;">Task</span>);</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">};</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">/**<span style="1;">   </span></span><span style="yes;">等待任务调度的获取线程池函数</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="宋体;"><span style="small;"><span style="yes;" lang="EN-US"><span style="yes;">    </span>@return<span style="1;">  </span>CThreadPool &amp; - </span><span style="yes;">返回线程池对象</span></span><span style="yes;" lang="EN-US"><span style="small;"><span style="1;">         </span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">*/</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">CThreadPool</span><span style="yes;" lang="EN-US"> &amp; <span style="black;">CWaitTaskScheduler</span>::<span style="black;">GetThreadPool</span>()</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="blue;">return</span> <span style="black;">m_ThreadPool</span>;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">}</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">/**<span style="1;">   </span></span><span style="yes;">等待任务调度的原子增加任务</span><span style="yes;" lang="EN-US">Id</span><span style="yes;">函数</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="宋体;"><span style="small;"><span style="yes;" lang="EN-US"><span style="yes;">    </span>@return<span style="1;">  </span>int - </span><span style="yes;">返回原子加后的任务</span></span><span style="yes;" lang="EN-US"><span style="small;">Id.<span style="1;">        </span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">*/</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">LONG</span><span style="yes;" lang="EN-US"> <span style="black;">CWaitTaskScheduler</span>::<span style="black;">AtomicIncrementTaskId</span>()</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="black;">LONG</span> <span style="black;">Id</span> = <span style="black;">AtomicIncrement</span>(&amp;<span style="black;">m_lTaskId</span>);</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="blue;">return</span> <span style="black;">Id</span>;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">}</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">/**<span style="1;">   </span></span><span style="yes;">等待任务调度的生成当前线程的本地任务</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US"><span style="yes;">    </span></span><span style="yes;">任务被放入当前线程的本地队列中</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="宋体;"><span style="small;"><span style="yes;" lang="EN-US"><span style="1;">         </span>@param<span style="1;">  </span>TASK &amp;Task - </span><span style="yes;">待执行的任务</span></span><span style="yes;" lang="EN-US"><span style="small;"><span style="1;"> </span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="宋体;"><span style="small;"><span style="yes;" lang="EN-US"><span style="1;">         </span>@return<span style="1;">  </span>void - </span><span style="yes;">无</span></span><span style="yes;" lang="EN-US"><span style="small;"><span style="1;">  </span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">*/</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">void</span><span style="yes;" lang="EN-US"> <span style="black;">CWaitTaskScheduler</span>::<span style="black;">SpawnLocalTask</span>(<span style="black;">CWaitTask</span> &amp;<span style="black;">Task</span>) </span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US"><span style="yes;">    </span>//</span><span style="yes;">将任务放入本地队列中</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="black;">m_DQueue</span>.<span style="black;">PushToLocalQueue</span>(<span style="black;">Task</span>);</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">};</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">/**<span style="1;">   </span></span><span style="yes;">等待任务调度的生成任务函数</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US"><span style="yes;">    </span></span><span style="yes;">生成的任务被放入分布式队列中</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="宋体;"><span style="small;"><span style="yes;" lang="EN-US"><span style="1;">         </span>@param<span style="1;">  </span>TASK &amp;Task - </span><span style="yes;">待执行的任务</span></span><span style="yes;" lang="EN-US"><span style="small;"><span style="1;"> </span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="宋体;"><span style="small;"><span style="yes;" lang="EN-US"><span style="1;">         </span>@return<span style="1;">  </span>void - </span><span style="yes;">无</span></span><span style="yes;" lang="EN-US"><span style="small;"><span style="1;">  </span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">*/</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">void</span><span style="yes;" lang="EN-US"> <span style="black;">CWaitTaskScheduler</span>::<span style="black;">SpawnTask</span>(<span style="black;">CWaitTask</span> &amp;<span style="black;">Task</span>) </span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="blue;">if</span> ( <span style="black;">m_lTaskId</span> &lt; <span style="black;">m_ThreadPool</span>.<span style="black;">GetThreadCount</span>() )</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span>{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US"><span style="yes;">        </span>//</span><span style="yes;">依次唤醒各个挂起的线程</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span><span style="black;">LONG</span> <span style="black;">Id</span> = <span style="black;">AtomicIncrement</span>(&amp;<span style="black;">m_lTaskId</span>);</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span><span style="blue;">if</span> ( <span style="black;">Id</span> &lt; <span style="black;">m_ThreadPool</span>.<span style="black;">GetThreadCount</span>() )</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span>{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US"><span style="yes;">            </span>//</span><span style="yes;">下面之所以可以对其他线程的本地队列进行无同步的操作，是因为</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US"><span style="yes;">            </span>// </span><span style="yes;">访问这些队列的线程在进队操作之后才开始运行</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">            </span><span style="black;">m_DQueue</span>.<span style="black;">PushToLocalQueue</span>(<span style="black;">Task</span>, <span style="black;">Id</span>);</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">            </span><span style="black;">m_ThreadPool</span>.<span style="black;">ExecThread</span>(<span style="black;">Id</span>);</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span>}</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span><span style="blue;">else</span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span>{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">            </span><span style="black;">m_DQueue</span>.<span style="black;">EnQueue</span>(<span style="black;">Task</span>);</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span>}</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span>}</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="blue;">else</span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span>{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US"><span style="yes;">        </span>//</span><span style="yes;">先判断共享队列是否满，如果未满则放入共享队列中</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US"><span style="yes;">        </span>//</span><span style="yes;">如果满了则放入本地队列中</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span><span style="black;">m_DQueue</span>.<span style="black;">EnQueue</span>(<span style="black;">Task</span>);</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span>}</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">};</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">/**<span style="1;">   </span></span><span style="yes;">等待任务调度的启动根线程函数</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="宋体;"><span style="small;"><span style="yes;" lang="EN-US"><span style="1;">         </span>@param<span style="1;">  </span>TASK &amp;Task - </span><span style="yes;">要执行的最初任务</span></span><span style="yes;" lang="EN-US"><span style="small;"><span style="1;"> </span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="宋体;"><span style="small;"><span style="yes;" lang="EN-US"><span style="1;">         </span>@return<span style="1;">  </span>void - </span><span style="yes;">无</span></span><span style="yes;" lang="EN-US"><span style="small;"><span style="1;">  </span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">*/</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">void</span><span style="yes;" lang="EN-US"> <span style="black;">CWaitTaskScheduler</span>::<span style="black;">BeginRootThread</span>(<span style="black;">CWaitTask</span> &amp;<span style="black;">Task</span>)</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="black;">m_lTaskId</span> = 0;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="black;">m_ThreadPool</span>.<span style="black;">CreateThreadPool</span>(<span style="black;">m_StartFunc</span>, <span style="blue;">this</span>, 0);</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="black;">m_DQueue</span>.<span style="black;">PushToLocalQueue</span>(<span style="black;">Task</span>, 0);</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="black;">m_ThreadPool</span>.<span style="black;">ExecThread</span>( 0 );<span style="yes;">  </span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="black;">m_ThreadPool</span>.<span style="black;">WaitAllThread</span>();</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">}</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">/**<span style="1;">   </span></span><span style="yes;">等待任务调度的线程池入口函数</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="宋体;"><span style="small;"><span style="yes;" lang="EN-US"><span style="1;">         </span>@param<span style="1;">  </span>void *pArgs - CWaitTaskScheduler</span><span style="yes;">类型的参数</span></span><span style="yes;" lang="EN-US"><span style="small;"><span style="1;">     </span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="宋体;"><span style="small;"><span style="yes;" lang="EN-US"><span style="1;">         </span>@return<span style="1;">  </span>unsigned int WINAPI - </span><span style="yes;">返回</span></span><span style="yes;" lang="EN-US"><span style="small;"><span style="1;">   </span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">*/</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">static</span><span style="yes;" lang="EN-US"> <span style="blue;">unsigned</span> <span style="blue;">int</span> <span style="black;">WINAPI</span> <span style="black;">WaitTaskScheduler_StartFunc</span>(<span style="blue;">void</span> *<span style="black;">pArgs</span>)</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="black;">CWaitTaskScheduler</span><span style="yes;">  </span>*<span style="black;">pSched</span> = (<span style="black;">CWaitTaskScheduler</span> *)<span style="black;">pArgs</span>;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="black;">CWaitTask</span><span style="yes;">    </span><span style="black;">Task</span>;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="blue;">int</span><span style="yes;">     </span><span style="black;">nRet</span>;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="blue;">for</span> ( ;; )</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span>{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span><span style="black;">nRet</span> = <span style="black;">pSched</span>-&gt;<span style="black;">GetTask</span>(<span style="black;">Task</span>);</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span><span style="blue;">if</span> ( <span style="black;">nRet</span> == <span style="black;">CAPI_FAILED</span> )</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span>{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">            </span><span style="black;">CThreadPool</span> &amp;<span style="black;">ThreadPool</span> = <span style="black;">pSched</span>-&gt;<span style="black;">GetThreadPool</span>();</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">            </span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US"><span style="yes;">            </span>// </span><span style="yes;">唤醒一个挂起的线程</span><span style="yes;" lang="EN-US">,</span><span style="yes;">防止任务数量小于</span><span style="yes;" lang="EN-US">CPU</span><span style="yes;">核数时，</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US"><span style="yes;">            </span>// </span><span style="yes;">仍然有任务处于挂起状态</span><span style="yes;" lang="EN-US">,</span><span style="yes;">从而导致</span><span style="yes;" lang="EN-US">WaitAllThread()</span><span style="yes;">处于死等状态</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US"><span style="yes;">            </span>// </span><span style="yes;">这个唤醒过程是一个串行的过程，被唤醒的任务会继续唤醒一个挂起线程</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">            </span><span style="black;">LONG</span> <span style="black;">Id</span> = <span style="black;">pSched</span>-&gt;<span style="black;">AtomicIncrementTaskId</span>();</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">            </span><span style="blue;">if</span> ( <span style="black;">Id</span> &lt; <span style="black;">ThreadPool</span>.<span style="black;">GetThreadCount</span>() )</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">            </span>{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">                </span><span style="black;">ThreadPool</span>.<span style="black;">ExecThread</span>(<span style="black;">Id</span>);</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">            </span>}</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">            </span><span style="blue;">break</span>;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span>}</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span>(*(<span style="black;">Task</span>.<span style="black;">func</span>))(<span style="black;">Task</span>.<span style="black;">pArg</span>);</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span><span style="blue;">if</span> ( <span style="black;">Task</span>.<span style="black;">pCount</span> != <span style="black;">NULL</span> )</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span>{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">            </span><span style="black;">AtomicDecrement</span>(<span style="black;">Task</span>.<span style="black;">pCount</span>);</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span>}</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span>}</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="blue;">return</span> 0;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">}</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US">void</span><span style="yes;" lang="EN-US"> <span style="black;">CWaitTaskScheduler</span>::<span style="black;">SpawnTaskArrayAndWait</span>(<span style="black;">CTaskArray</span> *<span style="black;">pTaskArray</span>)</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="blue;">int</span> <span style="black;">i</span>;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="blue;">for</span> (<span style="black;">i</span> = 0; <span style="black;">i</span> &lt; <span style="black;">pTaskArray</span>-&gt;<span style="black;">GetTaskCount</span>(); <span style="black;">i</span>++ )</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span>{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span><span style="black;">SpawnTask</span>(<span style="black;">pTaskArray</span>-&gt;<span style="black;">m_pTaskArray</span>[<span style="black;">i</span>]);</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span>}</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US"><span style="yes;">    </span>// </span><span style="yes;">等待上面的任务列表全部执行完成</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="blue;">while</span> ( <span style="black;">pTaskArray</span>-&gt;<span style="black;">GetCurTaskCount</span>() != 0 )</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span>{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US"><span style="yes;">        </span>//</span><span style="yes;">切换到其他任务上执行，即偷取其他任务来执行</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span><span style="black;">CWaitTask</span> <span style="black;">task</span>;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US"><span style="yes;">        </span><span style="blue;">int</span> <span style="black;">nRet</span> = <span style="black;">GetTask</span>(<span style="black;">task</span>); //</span><span style="yes;">从分布式队列中偷取任务</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span><span style="blue;">if</span> ( <span style="black;">nRet</span> == <span style="black;">CAPI_FAILED</span> )</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span>{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US"><span style="yes;">            </span><span style="black;">CAPI_Yield</span>(); //</span><span style="yes;">将当前线程暂时切换到后台</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span>}</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span><span style="blue;">else</span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span>{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US"><span style="yes;">            </span>(*(<span style="black;">task</span>.<span style="black;">func</span>))(<span style="black;">task</span>.<span style="black;">pArg</span>); //</span><span style="yes;">执行偷取到的任务</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">            </span><span style="blue;">if</span> ( <span style="black;">task</span>.<span style="black;">pCount</span> != <span style="black;">NULL</span> )</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">            </span>{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US"><span style="yes;">                </span><span style="black;">AtomicDecrement</span>(<span style="black;">task</span>.<span style="black;">pCount</span>); //</span><span style="yes;">将任务计数减</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">            </span>} </span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span>}</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span>}</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US"><span style="yes;">    </span>//pTaskArray-&gt;GetCurTaskCount()</span><span style="yes;">返回表示所有需要等待的任务都执行完成</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US"><span style="yes;">  </span><span style="yes;">  </span>//</span><span style="yes;">此时可以退出等待了</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="blue;">return</span>;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">}</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;"> </span></span></p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/zh-cn/blogs/2009/12/08/400002857/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>多核动态任务调度的进一步探索(5)</title>
		<link>http://software.intel.com/zh-cn/blogs/2009/12/08/400002854/</link>
		<comments>http://software.intel.com/zh-cn/blogs/2009/12/08/400002854/#comments</comments>
		<pubDate>Tue, 08 Dec 2009 02:14:37 +0000</pubDate>
		<dc:creator>Zhouweiming 周伟明</dc:creator>
				<category><![CDATA[其他]]></category>
		<category><![CDATA[博客征文专栏]]></category>
		<category><![CDATA[并行计算]]></category>
		<category><![CDATA[开放源代码]]></category>

		<guid isPermaLink="false">http://software.intel.com/zh-cn/blogs/2009/12/08/400002854/</guid>
		<description><![CDATA[完整的代码存放在开源项目MCAPI(原CAPI项目，迁移到Sourceforge后改名为MCAPI)中，由于这部分代码暂未发布，因此我会把完整的代码贴在后面，当然，需要的话，你也可以直接到sourceforge的svn库中去将代码取下来，取代码的地址为https://mcapi.svn.sourceforge.net/svnroot/mcapi （需要用svn客户端去取，在Linux下，可以使用命令svn co https:// mcapi.svn.sourceforge.net/svnroot/mcapi mcapi来获取代码） 由于有依赖关系的调度其他部分和前面列出的几篇文中中讲的动态任务调度类似，因此就不再详述了，下面列出它的完整代码。 // 下面是CWaitTaskScheduler.h头文件内容 class CWaitTask { public:     THREADFUNC      func;         //任务执行函数     void            *pArg;        //任务函数的参数     volatile LONG   *pCount;      //任务组计数指针，为等待一组任务执行完而设计       CWaitTask(); };   class CTaskArray { public:     CWaitTask   *  m_pTaskArray;     int            m_nTaskArraySize;     LONG         m_lTaskCount;     volatile LONG   m_lCurTaskCount; //任务组中任务个数计数，                                  //可以用来为等待一组任务执行完进行判断     CTaskArray(int nTaskArraySize); [...]]]></description>
			<content:encoded><![CDATA[<p class="a" style="21pt;"><span style="small;"><span style="minor-latin;">完整的代码存放在开源项目</span><span style="宋体;"><span lang="EN-US">MCAPI(</span><span style="minor-latin;">原</span><span lang="EN-US">CAPI</span><span style="minor-latin;">项目，迁移到</span><span lang="EN-US">Sourceforge</span><span style="minor-latin;">后改名为</span><span lang="EN-US">MCAPI)</span><span style="minor-latin;">中，由于这部分代码暂未发布，因此我会把完整的代码贴在后面，当然，需要的话，你也可以直接到</span><span lang="EN-US">sourceforge</span><span style="minor-latin;">的</span><span lang="EN-US">svn</span><span style="minor-latin;">库中去将代码取下来，取代码的地址为</span><span lang="EN-US"><a href="https://mcapi.svn.sourceforge.net/svnroot/mcapi">https://mcapi.svn.sourceforge.net/svnroot/mcapi</a> </span><span style="minor-latin;">（需要用</span><span lang="EN-US">svn</span><span style="minor-latin;">客户端去取，在</span><span lang="EN-US">Linux</span><span style="minor-latin;">下，可以使用命令</span><span lang="EN-US">svn co https:// mcapi.svn.sourceforge.net/svnroot/mcapi mcapi</span></span><span style="minor-latin;">来获取代码）</span></span></p>
<p class="a" style="21pt;"><span style="minor-latin;"><span style="small;">由于有依赖关系的调度其他部分和前面列出的几篇文中中讲的动态任务调度类似，因此就不再详述了，下面列出它的完整代码。</span></span></p>
<p class="a" style="21pt;"><span style="宋体;"><span style="small;"><span lang="EN-US">// </span><span style="minor-latin;">下面是</span><span lang="EN-US">CWaitTaskScheduler.h</span><span style="minor-latin;">头文件内容</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="宋体;">class CWaitTask {</span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="宋体;">public:</span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="宋体;"><span style="small;"><span lang="EN-US"><span style="yes;">    </span>THREADFUNC<span style="yes;">      </span>func;<span style="yes;">         </span>//</span><span style="minor-latin;">任务执行函数</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="宋体;"><span style="small;"><span lang="EN-US"><span style="yes;">    </span>void<span style="yes;">            </span>*pArg;<span style="yes;">        </span>//</span><span style="minor-latin;">任务函数的参数</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="宋体;"><span style="small;"><span lang="EN-US"><span style="yes;">    </span>volatile LONG<span style="yes;">   </span>*pCount;<span style="yes;">      </span>//</span><span style="minor-latin;">任务组计数指针，为等待一组任务执行完而设计</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span>CWaitTask();</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="宋体;">};</span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">class <span style="black;">CTaskArray</span> {</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;">public:</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="black;">CWaitTask</span><span style="yes;">   </span>*<span style="yes;">  </span><span style="black;">m_pTaskArray</span>;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span>int<span style="yes;">            </span><span style="black;">m_nTaskArraySize</span>;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="black;">LONG</span><span style="yes;">         </span><span style="black;">m_lTaskCount</span>;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US"><span style="yes;">    </span>volatile <span style="black;">LONG</span><span style="yes;">  </span><span style="yes;"> </span><span style="black;">m_lCurTaskCount</span>; <span style="green;">//</span></span><span style="yes;">任务组中任务个数计数，</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span style="yes;" lang="EN-US"><span style="yes;">                                 </span><span style="green;">//</span></span><span style="yes;">可以用来为等待一组任务执行完进行判断</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="black;">CTaskArray</span>(int <span style="black;">nTaskArraySize</span>);</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span>~<span style="black;">CTaskArray</span>();</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="black;">INT</span> <span style="black;">AddTask</span>(<span style="black;">THREADFUNC</span> <span style="black;">func</span>, void *<span style="black;">pArg</span>);</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="black;">LONG</span> <span style="black;">GetTaskCount</span>();</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><span style="black;">LONG</span> <span style="black;">GetCurTaskCount</span>();</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="yes;" lang="EN-US"><span style="宋体;">};</span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="宋体;">class CWaitTaskScheduler {</span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="宋体;">private:</span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span>CThreadPool<span style="yes;">     </span>m_ThreadPool;//(TaskScheduler_StartFunc, NULL, 0);</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span>CDistributedQueue&lt;CWaitTask, CLocalQueue&lt;CWaitTask&gt;,<span style="yes;">    </span></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span>CStealQueue&lt;CWaitTask&gt;&gt; m_DQueue;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="宋体;"><span style="small;"><span lang="EN-US"><span style="yes;">    </span>THREADFUNC<span style="yes;">      </span>m_StartFunc;<span style="yes;">  </span>//</span><span style="minor-latin;">为线程池使用的线程入口函数指针</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="宋体;"><span style="small;"><span lang="EN-US"><span style="yes;">    </span>LONG<span style="yes;">  </span>volatile<span style="yes;">  </span>m_lTaskId;<span style="yes;">    </span>//Task Id,</span><span style="minor-latin;">用于判断是否唤醒对应的线程</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="宋体;">public:</span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span>CWaitTaskScheduler();</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="yes;"><span style="宋体;">    </span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="yes;"><span style="宋体;">            </span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="宋体;"><span style="small;"><span lang="EN-US"><span style="yes;">    </span>//</span><span style="minor-latin;">下面三个函数为调度器的使用者使用</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span>void SpawnLocalTask(CWaitTask &amp;Task);</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span>void SpawnTask(CWaitTask &amp;Task);</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span>void SpawnTaskArrayAndWait(CTaskArray *pTaskArray);</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span>void BeginRootThread(CWaitTask &amp;Task);</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="宋体;">};</span></span></p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/zh-cn/blogs/2009/12/08/400002854/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>多核动态任务调度的进一步探索(4)</title>
		<link>http://software.intel.com/zh-cn/blogs/2009/12/08/400002847/</link>
		<comments>http://software.intel.com/zh-cn/blogs/2009/12/08/400002847/#comments</comments>
		<pubDate>Tue, 08 Dec 2009 02:13:48 +0000</pubDate>
		<dc:creator>Zhouweiming 周伟明</dc:creator>
				<category><![CDATA[博客征文专栏]]></category>
		<category><![CDATA[并行计算]]></category>
		<category><![CDATA[开放源代码]]></category>

		<guid isPermaLink="false">http://software.intel.com/zh-cn/blogs/2009/12/08/400002847/</guid>
		<description><![CDATA[首先，我们要等待一组任务，可以设计一个计数变量，每完成一个任务，让计数减1，计数为0时表示所有的任务都完成了，这时可以往下继续执行了，只要计数不为0，那么程序就不能往下执行。下图是任务计数的一个示意。         当任务计数不为0时，必须等待其他任务完成，在通常的做法中，都是要用一个栅障来进行等待，实际上，判断计数不为0时，线程可以不进行等待，去偷取其他线程的任务执行，这样线程就不用空等，同时因为在执行其他线程的任务，也不会往下执行，保证了任务的执行时序和依赖关系。          下面给出关键部分的实现代码：  void CWaitTaskScheduler::SpawnTaskArrayAndWait(CTaskArray *pTaskArray) {     int i;     for (i = 0; i &#60; pTaskArray-&#62;GetTaskCount(); i++ )                    SpawnTask(pTaskArray-&#62;m_pTaskArray[i]);     // 等待上面的任务列表全部执行完成 while ( pTaskArray-&#62;GetCurTaskCount() != 0 )      { //切换到其他任务上执行，即偷取其他任务来执行         CWaitTask task;         int nRet = GetTask( task );  //从分布式队列中偷取任务         if ( nRet == CAPI_FAILED [...]]]></description>
			<content:encoded><![CDATA[<p class="a" style="21pt;"><span style="small;"><span style="minor-latin;">首先，我们要等待一组任务，可以设计一个计数变量，每完成一个任务，让计数减</span><span style="宋体;"><span lang="EN-US">1</span><span style="minor-latin;">，计数为</span><span lang="EN-US">0</span><span style="minor-latin;">时表示所有的任务都完成了，这时可以往下继续执行了，只要计数不为</span><span lang="EN-US">0</span></span><span style="minor-latin;">，那么程序就不能往下执行。下图是任务计数的一个示意。</span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"> </p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="宋体;"> <a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2009/12/taskscheduler7.gif"><img class="alignnone size-full wp-image-400002850" src="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2009/12/taskscheduler7.gif" alt="" width="414" height="187" /></a></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="宋体;"><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2009/12/taskscheduler8.gif"><img class="alignnone size-full wp-image-400002851" src="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2009/12/taskscheduler8.gif" alt="" width="500" height="171" /></a></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"> </p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="a" style="21pt;"><span style="small;"><span style="minor-latin;">当任务计数不为</span><span style="宋体;"><span lang="EN-US">0</span><span style="minor-latin;">时，必须等待其他任务完成，在通常的做法中，都是要用一个栅障来进行等待，实际上，判断计数不为</span><span lang="EN-US">0</span></span><span style="minor-latin;">时，线程可以不进行等待，去偷取其他线程的任务执行，这样线程就不用空等，同时因为在执行其他线程的任务，也不会往下执行，保证了任务的执行时序和依赖关系。</span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="宋体;"><span style="small;"><span lang="EN-US"><span style="1;">         </span></span><span style="minor-latin;">下面给出关键部分的实现代码：</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="宋体;"> </span></span><strong><span style="accent2;" lang="EN-US"><span style="宋体;">void CWaitTaskScheduler::SpawnTaskArrayAndWait(CTaskArray *pTaskArray) </span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="宋体;">{</span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span>int i;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span>for (i = 0; i &lt; pTaskArray-&gt;GetTaskCount(); i++ ) </span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="small;"><span style="宋体;"><span style="2;">                   </span>SpawnTask(pTaskArray-&gt;m_pTaskArray[i]);</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="yes;"><span style="宋体;">    </span></span></span></p>
<p class="MsoNormal" style="21pt;"><span style="宋体;"><span style="small;"><span lang="EN-US">// </span><span style="minor-latin;">等待上面的任务列表全部执行完成</span></span></span></p>
<p class="MsoNormal" style="20.25pt;"><span lang="EN-US"><span style="small;"><span style="宋体;">while ( pTaskArray-&gt;GetCurTaskCount() != 0 )<span style="yes;">     </span></span></span></span></p>
<p class="MsoNormal" style="1.5;"><span lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;"> </span>{</span></span></span></p>
<p class="MsoNormal" style="3.9;"><span style="宋体;"><span style="small;"><span lang="EN-US">//</span><span style="minor-latin;">切换到其他任务上执行，即偷取其他任务来执行</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span>CWaitTask task;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="宋体;"><span style="small;"><span lang="EN-US"><span style="yes;">        </span>int nRet = GetTask( task ); <span style="yes;"> </span>//</span><span style="minor-latin;">从分布式队列中偷取任务</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span>if ( nRet == CAPI_FAILED )</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="宋体;"><span style="small;"><span lang="EN-US"><span style="yes;">            </span>CAPI_Yield();<span style="yes;">  </span>//</span><span style="minor-latin;">将当前线程暂时切换到后台</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span>else<span style="yes;">   </span></span></span></span></p>
<p class="MsoNormal" style="3.5;"><span lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;"> </span>{</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="宋体;"><span style="small;"><span lang="EN-US"><span style="yes;">            </span>(*(task.func))( task.pArg ); <span style="yes;"> </span>//</span><span style="minor-latin;">执行偷取到的任务</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">            </span>if ( task.pCount != NULL ) </span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="宋体;"><span style="small;"><span lang="EN-US"><span style="yes;">                  </span>AtomicDecrement( task.pCount ); //</span><span style="minor-latin;">将任务计数减</span></span><span lang="EN-US"><span style="small;">1</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">        </span>}</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span>}</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="宋体;"><span style="small;"><span lang="EN-US"><span style="yes;">    </span>//GetCurTaskCount()</span><span style="minor-latin;">返回</span><span lang="EN-US">0</span><span style="minor-latin;">表示所有需要等待的任务都执行完成</span><span lang="EN-US">, </span><span style="minor-latin;">此时可以退出等待了</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span>return;</span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="宋体;">}</span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="a" style="21pt;"><span style="small;"><span style="12.0pt;">上面的</span><span style="宋体;"><span lang="EN-US">SpawnTaskArrayAndWait</span><span style="12.0pt;" lang="EN-US">()</span><span style="12.0pt;">函数中，先生成一组任务，然后用一个</span><span style="12.0pt;" lang="EN-US">while</span><span style="12.0pt;">循环来等待生成的一组任务全部执行完</span><span style="minor-latin;">，可以看到在</span><span lang="EN-US">while</span><span style="minor-latin;">循环中，只有当偷取任务失败时，才会调用</span><span lang="EN-US">CAPI_Yield()</span><span style="minor-latin;">函数将线程切换到后台，其他时候一直都是处于执行状态的，没有调用任何真正意义的等待函数（如</span><span lang="EN-US">Windows</span><span style="minor-latin;">系统中的</span><span lang="EN-US">WaitForSingleObject</span></span><span style="minor-latin;">）来进行等待，寥寥数行代码就将一个有依赖关系的动态任务调度的最核心部分给实现了。</span></span></p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/zh-cn/blogs/2009/12/08/400002847/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>多核动态任务调度的进一步探索(2)</title>
		<link>http://software.intel.com/zh-cn/blogs/2009/12/08/400002843/</link>
		<comments>http://software.intel.com/zh-cn/blogs/2009/12/08/400002843/#comments</comments>
		<pubDate>Tue, 08 Dec 2009 02:13:32 +0000</pubDate>
		<dc:creator>Zhouweiming 周伟明</dc:creator>
				<category><![CDATA[博客征文专栏]]></category>
		<category><![CDATA[并行计算]]></category>
		<category><![CDATA[开放源代码]]></category>

		<guid isPermaLink="false">http://software.intel.com/zh-cn/blogs/2009/12/08/400002843/</guid>
		<description><![CDATA[对于矩阵乘法  C =  A × B，通常的做法是将矩阵进行分块相乘，如下图所示：       从上图可以看出这种分块相乘总共用了8次乘法，当然对于子矩阵相乘（如A0×B0），还可以继续递归使用分块相乘。对于中小矩阵来说，很适合使用这种分块乘法，但是对于大矩阵来说，递归的次数较多，如果能减少每次分块乘法的次数，那么性能将可以得到很好的提高。 Strassen矩阵乘法就是采用了一个简单的运算技巧，将上面的8次矩阵相乘变成了7次乘法，看别小看这减少的1次乘法，因为每递归1次，性能就提高了1/8，比如对于1024*1024的矩阵，第1次先分解成7次512*512的矩阵相乘，对于512*512的矩阵，又可以继续递归分解成256*256的矩阵相乘，…，一直递归下去，假设分解到64*64的矩阵大小后就不再递归，那么所花的时间将是分块矩阵乘法的(7/8) * (7/8) * (7/8) * (7/8) = 0.586倍，提高了快接近一倍。当然这是理论上的值，因为实际上strassen乘法增加了其他运算开销，实际性能会略低一点。 下面就是Strassen矩阵乘法的实现方法，     M1 = (A0 + A3) × (B0 + B3)     M2 = (A2 + A3) × B0     M3 = A0 × (B1 - B3)     M4 = A3 × (B2 - B0)     [...]]]></description>
			<content:encoded><![CDATA[<p class="a" style="21pt;"><span style="small;"><span style="minor-latin;">对于矩阵乘法</span><span style="宋体;"><span lang="EN-US"><span style="yes;">  </span>C = <span style="yes;"> </span>A </span><span style="minor-latin;">×</span> <span lang="EN-US">B</span></span><span style="minor-latin;">，通常的做法是将矩阵进行分块相乘，如下图所示：</span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="宋体;"> <a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2009/12/taskscheduler6.gif"><img class="alignnone size-full wp-image-400002842" src="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2009/12/taskscheduler6.gif" alt="" width="500" height="335" /></a></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"> </p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="a" style="21pt;"><span style="small;"><span style="minor-latin;">从上图可以看出这种分块相乘总共用了</span><span style="宋体;"><span lang="EN-US">8</span><span style="minor-latin;">次乘法，当然对于子矩阵相乘（如</span><span lang="EN-US">A0</span><span style="minor-latin;">×</span><span lang="EN-US">B0</span></span><span style="minor-latin;">），还可以继续递归使用分块相乘。对于中小矩阵来说，很适合使用这种分块乘法，但是对于大矩阵来说，递归的次数较多，如果能减少每次分块乘法的次数，那么性能将可以得到很好的提高。</span></span></p>
<p class="a" style="21pt;"><span style="宋体;"><span style="small;"><span lang="EN-US">Strassen</span><span style="minor-latin;">矩阵乘法就是采用了一个简单的运算技巧，将上面的</span><span lang="EN-US">8</span><span style="minor-latin;">次矩阵相乘变成了</span><span lang="EN-US">7</span><span style="minor-latin;">次乘法，看别小看这减少的</span><span lang="EN-US">1</span><span style="minor-latin;">次乘法，因为每递归</span><span lang="EN-US">1</span><span style="minor-latin;">次，性能就提高了</span><span lang="EN-US">1/8</span><span style="minor-latin;">，比如对于</span><span lang="EN-US">1024*1024</span><span style="minor-latin;">的矩阵，第</span><span lang="EN-US">1</span><span style="minor-latin;">次先分解成</span><span lang="EN-US">7</span><span style="minor-latin;">次</span><span lang="EN-US">512*512</span><span style="minor-latin;">的矩阵相乘，对于</span><span lang="EN-US">512*512</span><span style="minor-latin;">的矩阵，又可以继续递归分解成</span><span lang="EN-US">256*256</span><span style="minor-latin;">的矩阵相乘，</span><span lang="EN-US">…</span><span style="minor-latin;">，一直递归下去，假设分解到</span><span lang="EN-US">64*64</span><span style="minor-latin;">的矩阵大小后就不再递归，那么所花的时间将是分块矩阵乘法的</span><span lang="EN-US">(7/8) * (7/8) * (7/8) * (7/8) = 0.586</span><span style="minor-latin;">倍，提高了快接近一倍。当然这是理论上的值，因为实际上</span><span lang="EN-US">strassen</span><span style="minor-latin;">乘法增加了其他运算开销，实际性能会略低一点。</span></span></span></p>
<p class="a" style="21pt;"><span style="small;"><span style="minor-latin;">下面就是</span><span lang="EN-US"><span style="宋体;">Strassen</span></span><span style="minor-latin;">矩阵乘法的实现方法，</span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span><strong>M1 = (A0 + A3) × (B0 + B3)</strong></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><strong><span style="PT-BR;" lang="EN-US"><span style="yes;"> </span></span></strong><strong><span style="PT-BR;" lang="PT-BR"><span style="yes;">   </span>M2 = (A2 + A3) × B0</span></strong></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span>M3 = A0 × (B1 - B3)</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span>M4 = A3 × (B2 - B0)</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span>M5 = (A0 + A1) × B3</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span>M6 = (A2 - A0) × (B0 + B1)</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span>M7 = (A1 - A3) × (B2 + B3)</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span>C0 = M1 + M4 - M5 + M7</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><strong><span style="PT-BR;" lang="PT-BR"><span style="yes;">    </span>C1 = M3 + M5</span></strong></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><strong><span style="PT-BR;" lang="PT-BR"><span style="yes;">    </span>C2 = M2 + M4</span></strong></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><strong><span style="PT-BR;" lang="PT-BR"><span style="yes;">    </span>C3 = M1 - M2 + M3 + M6 </span></strong></span></span></p>
<p class="a" style="21pt;"><span style="small;"><span style="PT-BR;">在求解</span><span style="宋体;"><span style="PT-BR;" lang="PT-BR">M1,M2,M3,M4,M5,M6,M7</span><span style="PT-BR;">时需要使用</span><span style="PT-BR;" lang="PT-BR">7</span></span><span style="PT-BR;">次矩阵乘法，其他都是矩阵加法和减法。</span></span></p>
<p class="a" style="21pt;"><span style="small;"><span style="PT-BR;">下面看看</span><span style="PT-BR;" lang="PT-BR"><span style="宋体;">Strassen</span></span><span style="PT-BR;">矩阵乘法的串行实现伪代码：</span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span lang="EN-US"><span style="small;"><span style="宋体;">Serial_StrassenMultiply(A, B, C)<span style="yes;">  </span></span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span lang="EN-US"><span style="宋体;">{</span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span>T1 = A0 + A3;</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span>T2 = B0 + B3;</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span>StrassenMultiply(T1, T2, M1);</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span>T1 = A2 + A3;</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span>StrassenMultiply(T1, B0, M2);</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span>T1 = (B1 - B3);</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><span lang="EN-US"><span style="yes;">    </span><strong>Strassen</strong></span><strong><span style="PT-BR;" lang="PT-BR">Multiply</span><span lang="EN-US"> (A0, T1, M3);</span></strong></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span lang="EN-US"><span style="yes;"><span style="宋体;"> </span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span>T1 = B2 - B0;</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span>StrassenMultiply(A3, T1, M4);</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="EN-US"><span style="yes;"><span style="宋体;"> </span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">   </span><span style="yes;"> </span>T1 = A0 + A1;</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">   </span><span style="yes;"> </span>StrassenMultiply(T1, B3, M5);<span style="yes;">        </span></span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="yes;"><span style="宋体;">    </span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span>T1 = A2 – A0;</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span>T2 = B0 + B1;</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span>StrassenMultiply(T1, T2, M6);</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span>T1 = A1 – A3;</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span>T2 = B2 + B3;</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span>StrassenMultiply(T1, T2, M7);</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><strong><span style="PT-BR;" lang="PT-BR"><span style="yes;">    </span>C0 = M1 + M4 - M5 + M7</span></strong></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><strong><span style="PT-BR;" lang="PT-BR"><span style="yes;">    </span>C1 = M3 + M5</span></strong></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><strong><span style="PT-BR;" lang="PT-BR"><span style="yes;">    </span>C2 = M2 + M4</span></strong></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><strong><span style="PT-BR;" lang="PT-BR"><span style="yes;">    </span>C3 = M1 - M2 + M3 + M6</span></strong></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span lang="EN-US"><span style="宋体;">}</span></span></strong></p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/zh-cn/blogs/2009/12/08/400002843/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>多核动态任务调度的进一步探索(3)</title>
		<link>http://software.intel.com/zh-cn/blogs/2009/12/08/400002845/</link>
		<comments>http://software.intel.com/zh-cn/blogs/2009/12/08/400002845/#comments</comments>
		<pubDate>Tue, 08 Dec 2009 02:13:03 +0000</pubDate>
		<dc:creator>Zhouweiming 周伟明</dc:creator>
				<category><![CDATA[博客征文专栏]]></category>
		<category><![CDATA[并行计算]]></category>
		<category><![CDATA[开放源代码]]></category>

		<guid isPermaLink="false">http://software.intel.com/zh-cn/blogs/2009/12/08/400002845/</guid>
		<description><![CDATA[如果使用动态任务调度来实现上面的Strassen矩阵乘法，通常的做法是将7次矩阵乘法变成7个任务来执行，但是，由于计算C0，C1，C2，C3时，必须先将M1,M2,M3,M4,M5,M6,M7计算好，因此生成了7个矩阵乘法任务后，必须在计算C0前，等待这7个任务全部完成。 下面给出动态任务调度实现Strassen矩阵相乘的伪代码。   Parallel_StrassenMultiply(A, B, C)  {     T1 = A0 + A3;     T2 = B0 + B3;     SpawnTaks(M1 = T1* T2);     T1 = A2 + A3;     SpawnTask(M2 = T1* B0);     T1 = (B1 - B3);     SpawnTask (M3 = A0 * T1);       T1 = B2 - B0; [...]]]></description>
			<content:encoded><![CDATA[<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="minor-latin;">如果使用动态任务调度来实现上面的</span><span style="宋体;"><span lang="EN-US">Strassen</span><span style="minor-latin;">矩阵乘法，通常的做法是将</span><span lang="EN-US">7</span><span style="minor-latin;">次矩阵乘法变成</span><span lang="EN-US">7</span><span style="minor-latin;">个任务来执行，但是，由于计算</span><span lang="EN-US">C0</span><span style="minor-latin;">，</span><span lang="EN-US">C1</span><span style="minor-latin;">，</span><span lang="EN-US">C2</span><span style="minor-latin;">，</span><span lang="EN-US">C3</span><span style="minor-latin;">时，必须先将</span><span style="PT-BR;" lang="PT-BR">M1,M2,M3,M4,M5,M6,M7</span><span style="PT-BR;">计算好，因此生成了</span><span style="PT-BR;" lang="PT-BR">7</span><span style="PT-BR;">个矩阵乘法任务后，必须在计算</span><span style="PT-BR;" lang="PT-BR">C0</span><span style="PT-BR;">前，等待这</span><span style="PT-BR;" lang="PT-BR">7</span></span><span style="PT-BR;">个任务全部完成。</span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="PT-BR;">下面给出动态任务调度实现</span><span style="PT-BR;" lang="PT-BR"><span style="宋体;">Strassen</span></span><span style="PT-BR;">矩阵相乘的伪代码。</span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span lang="EN-US"><span style="small;"><span style="宋体;">Parallel_StrassenMultiply(A, B, C)<span style="yes;">  </span></span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span lang="EN-US"><span style="宋体;">{</span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span>T1 = A0 + A3;</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span>T2 = B0 + B3;</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><strong><span style="accent2;" lang="PT-BR"><span style="yes;">    </span>SpawnTaks(M1 = T1* T2);</span></strong></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span>T1 = A2 + A3;</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><strong><span style="accent2;" lang="PT-BR"><span style="yes;">    </span>SpawnTask(M2 = T1* B0);</span></strong></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span>T1 = (B1 - B3);</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="accent2;" lang="EN-US"><span style="small;"><span style="宋体;"><span style="yes;">    </span><strong>SpawnTask (M3 = A0 * T1);</strong></span></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span lang="EN-US"><span style="yes;"><span style="宋体;"> </span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span>T1 = B2 - B0;</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><strong><span style="accent2;" lang="PT-BR"><span style="yes;">    </span>SpawnTask(M4 = A3 * T1);</span></strong></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="EN-US"><span style="yes;"><span style="宋体;"> </span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">   </span><span style="yes;"> </span>T1 = A0 + A1;</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><strong><span style="accent2;" lang="PT-BR"><span style="yes;">   </span><span style="yes;"> </span>StrassenMultiply(M5 = T1 * B3);<span style="yes;">        </span></span></strong></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="yes;"><span style="宋体;">    </span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span>T1 = A2 – A0;</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span>T2 = B0 + B1;</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><strong><span style="accent2;" lang="PT-BR"><span style="yes;">    </span>SpawnTask(M6 = T1 * T2);</span></strong></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span>T1 = A1 – A3;</span></span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span style="PT-BR;" lang="PT-BR"><span style="small;"><span style="宋体;"><span style="yes;">    </span>T2 = B2 + B3;</span></span></span></strong></p>
<p class="MsoNormal" style="20.25pt;"><strong><span style="accent2;" lang="PT-BR"><span style="small;"><span style="宋体;">StrassenMultiply(M7 = T1 * T2);</span></span></span></strong></p>
<p class="MsoNormal" style="20.25pt;"><strong><span style="accent2;" lang="PT-BR"><span style="宋体;"> </span></span></strong></p>
<p class="MsoNormal" style="20.25pt;"><span style="small;"><span style="宋体;"><strong><span style="accent2;" lang="PT-BR">Wait </span></strong><strong><span style="accent2;">上面</span></strong><strong><span style="accent2;" lang="PT-BR">7</span></strong><strong><span style="accent2;">个任务完成</span></strong></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><strong><span style="PT-BR;" lang="PT-BR"><span style="yes;">    </span>C0 = M1 + M4 - M5 + M7</span></strong></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><strong><span style="PT-BR;" lang="PT-BR"><span style="yes;">    </span>C1 = M3 + M5</span></strong></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><strong><span style="PT-BR;" lang="PT-BR"><span style="yes;">    </span>C2 = M2 + M4</span></strong></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span style="small;"><span style="宋体;"><strong><span style="PT-BR;" lang="PT-BR"><span style="yes;">    </span>C3 = M1 - M2 + M3 + M6</span></strong></span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><strong><span lang="EN-US"><span style="宋体;">}</span></span></strong></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="a" style="21pt;"><span style="small;"><span style="minor-latin;">要实现上面伪代码中的等待</span><span style="宋体;"><span lang="EN-US">7</span><span style="minor-latin;">个任务完成的功能是非常简单的，只要实现一个栅障</span><span lang="EN-US">(barrier)</span><span style="minor-latin;">一样的功能就可以了，不过简单地使用栅障功能会带来许多副作用，因为它可能会使某些线程陷入等待的空闲状态，我们必须做到某个线程对应的</span><span lang="EN-US">7</span><span style="minor-latin;">个任务未完成时，它不能空等，而需要去偷取属于其他线程的任务来执行，这样才能保证所有的线程都处于忙状态，使得</span><span lang="EN-US">CPU</span></span><span style="minor-latin;">核得到充分利用。</span></span></p>
<p class="a" style="21pt;"><span style="minor-latin;"><span style="small;">所以，我们的有依赖关系的任务调度不会使用简单的栅障来实现任务等待，而会采用更高效的方式来实现等待功能，最高效的等待方式是什么？<span style="accent2;">最高效的等待方式就是“不等待”</span>。有没有搞错啊？不是说要实现等待功能吗，怎么能用“不等待”来实现等待呢？</span></span></p>
<p class="a" style="21pt;"><span style="minor-latin;"><span style="small;">或许有人看到这里要头晕了，其实我自己也头都晕了，因为实在找不到好的方式来解释用“不等待”实现等待的问题，只好把老子的道德经里的“有中生无，无中生有”搬出来一下，简单地说就是<span style="accent2;">用“不等待”来生成“等待”</span>。</span></span></p>
<p class="a" style="21pt;"><span style="minor-latin;"><span style="small;">闲话少叙，还是看看具体的实现思想。</span></span></p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/zh-cn/blogs/2009/12/08/400002845/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>多核动态任务调度的进一步探索(1)</title>
		<link>http://software.intel.com/zh-cn/blogs/2009/12/08/400002840/</link>
		<comments>http://software.intel.com/zh-cn/blogs/2009/12/08/400002840/#comments</comments>
		<pubDate>Tue, 08 Dec 2009 02:12:21 +0000</pubDate>
		<dc:creator>Zhouweiming 周伟明</dc:creator>
				<category><![CDATA[博客征文专栏]]></category>
		<category><![CDATA[并行计算]]></category>
		<category><![CDATA[开放源代码]]></category>

		<guid isPermaLink="false">http://software.intel.com/zh-cn/blogs/2009/12/08/400002840/</guid>
		<description><![CDATA[讲解一个新的有依赖关系的动态任务调度算法，并以动态任务调度来实现并行Strassen乘法。]]></description>
			<content:encoded><![CDATA[<p class="MsoNormal" style="center;" align="center"><span style="minor-latin;">多核动态任务调度的进一步探索</span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="a" style="21pt;"><span style="small;"><span style="minor-latin;">多核中的动态任务调度算法可以说是多核三大算法之首，因为它可以将一些串行程序变成并行执行的。程序员只要按照一定接口规范写串行算法，就可以用动态任务调度器将其并行运行。</span><span style="宋体;"><span lang="EN-US">Intel TBB</span><span style="minor-latin;">库中就实现了一个动态任务调度算法，不过</span><span lang="EN-US">TBB</span><span style="minor-latin;">库中的实现代码量较大（大约有</span><span lang="EN-US">4000</span><span style="minor-latin;">多行代码），估计没有多少人能完全看得明白，我在开源</span><span lang="EN-US">MCAPI(</span><span style="minor-latin;">原</span><span lang="EN-US">CAPI</span><span style="minor-latin;">项目，迁移到</span><span lang="EN-US">Sourceforge</span><span style="minor-latin;">后改名为</span><span lang="EN-US">MCAPI)</span><span style="minor-latin;">库</span><span lang="EN-US">(</span><span style="minor-latin;">地址：</span><span lang="EN-US"><a href="http://sourceforge.net/projects/mcapi"><span style="#800080;">http://sourceforge.net/projects/mcapi</span></a>)</span><span style="minor-latin;">中也实现了几种不同类型的动态任务调度算法，这些实现中的任何一种都只用了两百行代码左右，其中有部分实现方法在今年</span><span lang="EN-US">5~6</span></span><span style="minor-latin;">月份时已撰文介绍了，文章链接如下：</span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><a href="http://software.intel.com/zh-cn/blogs/2009/05/30/400001866/"><span style="small;"><span style="minor-latin;" lang="EN-US"><span lang="EN-US">多核中的动态任务调度</span></span><span style="宋体;">(1)</span></span></a></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><a href="http://software.intel.com/zh-cn/blogs/2009/05/30/400001869/"><span style="small;"><span style="minor-latin;" lang="EN-US"><span lang="EN-US">多核中的动态任务调度</span></span><span style="宋体;">(2)</span></span></a></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><a href="http://software.intel.com/zh-cn/blogs/2009/05/30/400001874/"><span style="small;"><span style="minor-latin;" lang="EN-US"><span lang="EN-US">多核中的动态任务调度</span></span><span style="宋体;">(3)</span></span></a></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><a href="http://software.intel.com/zh-cn/blogs/2009/05/30/400001880/"><span style="small;"><span style="minor-latin;" lang="EN-US"><span lang="EN-US">多核中的动态任务调度</span></span><span style="宋体;">(4)</span></span></a></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><a href="http://software.intel.com/zh-cn/blogs/2009/05/31/parallel_for-1/"><span style="small;"><span style="minor-latin;" lang="EN-US"><span lang="EN-US">用动态任务调度器实现</span></span><span style="宋体;">Parallel_For <span style="minor-latin;" lang="EN-US"><span lang="EN-US">（</span></span>1</span><span style="minor-latin;" lang="EN-US"><span lang="EN-US">）</span></span></span></a></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><a href="http://software.intel.com/zh-cn/blogs/2009/05/31/parallel_for-2/"><span style="small;"><span style="minor-latin;" lang="EN-US"><span lang="EN-US">用动态任务调度器实现</span></span><span style="宋体;">Parallel_For <span style="minor-latin;" lang="EN-US"><span lang="EN-US">（</span></span>2</span><span style="minor-latin;" lang="EN-US"><span lang="EN-US">）</span></span></span></a></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><a href="http://software.intel.com/zh-cn/blogs/2009/05/31/parallel_for/"><span style="small;"><span style="minor-latin;" lang="EN-US"><span lang="EN-US">用</span></span><span style="宋体;">Parallel_For</span><span style="minor-latin;" lang="EN-US"><span lang="EN-US">进行并行快速排序</span></span></span></a></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><a href="http://software.intel.com/zh-cn/blogs/2009/05/31/parallel_for/#comment-25420"><span style="small;"><span style="minor-latin;" lang="EN-US"><span lang="EN-US">用</span></span><span style="宋体;">Parallel_For</span><span style="minor-latin;" lang="EN-US"><span lang="EN-US">进行并行快速排序</span></span></span></a></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><a href="http://software.intel.com/zh-cn/blogs/2009/05/31/parallel_for/#comment-25530"><span style="small;"><span style="minor-latin;" lang="EN-US"><span lang="EN-US">用</span></span><span style="宋体;">Parallel_For</span><span style="minor-latin;" lang="EN-US"><span lang="EN-US">进行并行快速排序</span></span></span></a></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="a" style="21pt;"><span style="small;"><span style="minor-latin;">上面这些文章中介绍的动态任务调度算法，也能实现将一些串行算法自动变成并行执行，不过这个算法的功能相比</span><span lang="EN-US"><span style="宋体;">TBB</span></span><span style="minor-latin;">中的动态任务调度算法功能上要差一些，因为它只能实现一些简单的无依赖关系的动态任务调度，当任务间存在依赖关系时，必须等待依赖的任务完成后，才能继续执行下面的任务。为了弥补上述动态任务调度功能上的不足，我在今年年初时设计了一个新的动态任务调度算法，可以实现有依赖关系的动态任务调度。</span></span></p>
<p class="a" style="21pt;"><span style="minor-latin;"><span style="small;">下面就是一种典型的有依赖关系的任务调度</span></span></p>
<p class="MsoNormal" style="list 36.0pt;"><span style="Wingdings;" lang="EN-US"><span style="Ignore;"><span style="small;">l</span><span style="7pt &quot;Times New Roman&quot;;">  </span></span></span><span style="minor-latin;"><span style="small;">将一个大的任务被拆分成多个小任务</span></span></p>
<p class="MsoNormal" style="list 36.0pt;"><span style="Wingdings;" lang="EN-US"><span style="Ignore;"><span style="small;">l</span><span style="7pt &quot;Times New Roman&quot;;">  </span></span></span><span style="minor-latin;"><span style="small;">需要等这多个小任务全部处理完，然后才能对多个小任务处理结果进行合并</span></span></p>
<p class="MsoNormal" style="list 36.0pt;"><span style="Wingdings;" lang="EN-US"><span style="Ignore;"><span style="small;">l</span><span style="7pt &quot;Times New Roman&quot;;">  </span></span></span><span style="minor-latin;"><span style="small;">拆分任务和对任务结果进行合并间需要进行等待</span></span></p>
<p class="MsoNormal" style="0cm 0cm 0pt;"><span lang="EN-US"><span style="宋体;"> </span></span></p>
<p class="a" style="21pt;"><span style="small;"><span style="minor-latin;">为了进一步说明问题，下面以并行</span><span lang="EN-US"><span style="宋体;">Strassen</span></span><span style="minor-latin;">矩阵乘法来说明这种有依赖关系的任务调度问题。</span></span></p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/zh-cn/blogs/2009/12/08/400002840/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

