自由行

2008-08-28

Thinking in Multi-thread

Filed under: 随笔 — thomas @ 23:13

http://blog.csdn.net/kevinkevin/archive/2008/08/26/2830460.aspx#883040

————————————————————————————————————–

单核CPU,多线程与性能

问题概述

单核CPU的计算机上, 多线程能够提高程序运行的性能吗? 这个问题看起来简单,实际很复杂,设计到多方面的因素. 首先我们要把概念搞清楚, 那就是什么是性能? 一般来说, 我们把运行一个任务所花的时间来评价性能, 所花的时间可以是在CPU, 也可能是在I/O操作上, 运行任务的程序, 也可能同时在运行另外若干的任务(吞吐量). 这里我们把概念给缩小一下:

我们这里把性能限制在一个程序运行一个任务, 这个任务是只消耗CPU资源(CPU bound), 所花的时间越小, 说明性能越好. 为了纯粹地说明问题, 我们排除了数据共享问题, 即线程之间不做任何同步动作, 完全隔离.

从理论上说,如果计算机只执行这一个测试程序, 那么单线程要比多线程性能好,因为多线程需要做线程上下文环境的切换; 而当计算机同时运行其他的进程, 假设其他进程里也有多个大量消耗CPU的任务, 那么我们的程序由于是多线程, 抢到CPU时间片的机会增多, 它的性能应该好于单线程.

理论上是这么回事, 但我们知道, 实践与理论是有差距的, 我们的测试不可能在真空环境中. 操作系统的实现有高度的戏剧性, 谁也不能预测实际的测试一定与理论相符, 另外在我们实际的运行环境中,各种情况导致的系统差异很大, 因为我们必须做一些测试.

MSDN上有一篇著名的文章<<Win32 Multithreading Performance>>, 里面讲的东西与我们很相近. 它主要论述的是串行计算和并行计算的性能比较, 我们直接拿它的例子, 进行一些更改, 来测试我们的假设.

首先讨论我们测试的主题与它的不同, 主要有2: 1, 我们讨论的任务是一个固定的任务, 而它里面讨论的是数个计算量不同的任务, 而计算不同的任务涉及到吞吐量的概念; 2, 我们讨论的是线程数量之间的比较(分别测试不同数量的线程), 而它只有单线程与多线程的比较.

1: 多个不同的任务并行处理

图案2: 一个固定的任务并行处理

测试程序介绍

一个任务在这里简化为一个持续占用CPU的计算, 为了测试的准确性, 中间不可以有任何的I/O操作, 例如:

for (int iCounter=0; iCounter<iLoopCount; iCounter++);

给定的任务量iDelay,单位是毫秒, 有一段模拟的代码, 从而把一秒的时间转换为循环数iLoopCount.里面所用的两个APIQueryPerformanceFrequencyQueryPerformanceCounter.

我们增加一个方法来取代OnWorstcase:

void CThreadlibtestView::OnFixTask()

{

if(!m_iNumberOfThreads)

{

MessageBeep(-1);

return;

};

for (int iLoop=0;iLoop<m_iNumberOfThreads;iLoop++)

{

m_iNumbers[iLoop]=(int)&m_tbConc[iLoop];

m_tbConc[iLoop].iId=iLoop;

if(iLoop==0)

m_tbConc[iLoop].iDelay=m_iDelay/m_iNumberOfThreads+m_iDelay%m_iNumberOfThreads;

else

m_tbConc[iLoop].iDelay=m_iDelay/m_iNumberOfThreads;

m_tbConc[iLoop].tbOutputTarget=this;

m_tbConc[iLoop].iStartOrder=0;

m_tbConc[iLoop].iEndOrder=0;

m_tbConc[iLoop].iTouchCount=0;

};

}

另外我们指定特定的任务量和线程数量:

int iTaskSize[]={100,500,1000,2000,4000};

int iThreadSize[]={2,5,10,15,20};

单线程时候我们调用OnSerial(), 多线程时调用OnConcurrent(), 线程数量分别取iThreadSize里的值.

测试次数仍然保持10, 取平均值, 整个测试我们分别运行两次, 第一次在负载很轻的计算机上运行, 第二次在同样的计算机上加载一个大负载的进程, 此进程里有十个线程, 每个线程都是基于CPU的密集计算, 程序如下:

DWORD WINAPI ThreadFunc(LPVOID lpParam)

{

DWORD busyTime=10;

while(true)

{

DWORD startTime=GetTickCount();

for(;GetTickCount()-startTime<=busyTime;)

;

Sleep(1);

}

return 0;

}

特别要注意的是, 两次计算不能各启动一个进程, 必须在一个进程中, 因为在程序开始,我们会算出1秒对应循环数, 而每次启动程序这个数字是不同的, 为了更有意义的比较,我们要求这个数字一定相同.

测试环境: CPU Intel Pentium M 1.7 G; 1047472KB RAM, Windows 2000 professional SP4.

一秒的循环数:146278208

测试结果

3: 在负载轻的系统上测试结果

4: 在负载重的系统上测试结果

结论和建议

根据测试结果,我们可以得出一些结论(针对单核CPU):

在负载轻的系统上, 多线程不适合处理基于CPU的任务,而在负载重的系统上,多线程可以帮助提高性能.

这是一个模糊和慎重的结论, 因为测试结果里的一些现象我也给不出合适的理由, 应该属于操作系统戏剧化不确定性的表现吧(操作系统会对某些线程动态提高优先级,但本例中的线程优先级保持不变.), 例如在负载轻的机器上, 20个线程和2个线程运行时间差异不大; 在负载重的机器上, 2个线程运行时间比单线程还长, 而当线程数量增加到5, 性能才有显著的提高.

所以我的建议是,在单核CPU机器上,处理CPU密集的任务时, 不推荐使用多线程, 除非你对目标机器非常的了解和确定,并经过严格的测试. 当然, 涉及到其他I/O操作的任务, 比如等待用户按键, 读取文件, 网络通讯等, 多线程才是正当其选的解决方案.

————————————————————————————————————–

对于一个任务有一定的规模,具有可分性,即大规模任务可以由小规模任务总和。使用不同数量的线程在单核机器运行,轻量负载和大负载下调度的开销是不确定的,所以有测试结果的不同。
但是多线程是为了解决多任务而产生的,而且是多种性质不同的任务。多线程方案所获得的性能是计算机系统的总体性能。
所以笔者关于多线程的分析有局限,多线程在单核机器的价值,在于多任务;而在多核计算机系统中,才能发挥多线程在性能方面的巨大优势。
多线程程序设计上面临很多挑战,关键是任务的可分性。对于复杂任务,子运算顺序依赖涉及同步时机问题,要想高效率起来必然导致程序的复杂性大大增加。

2008-08-19

刘翔退赛、观众退票引发的思考

Filed under: 随笔 — thomas @ 09:27

刘翔退赛后,有人很气愤进而退票。下面引述一段《新闻晨报》的评论。
“至于手中花钱买来的票(从犯罪分子手中高价购入的就别放桌面上说了,请主动配合公安机关调查),那跟张学友演唱会的票可不相同。不明确参加的选手,不明确最后的成绩,卖给你的是一张准许进鸟巢的路条,看到什么想到什么带回去什么都是未知。这就是奥运会和所有体育比赛的魅力。不能把流泪气愤绝望当享受的人,是不适合欣赏体育参与奥运的。Game是比赛,也是游戏。”
2008年08月19日07:41 新闻晨报

http://news.sina.com.cn/pl/2008-08-19/074116138687.shtml

其实还有一个有一个问题,刘翔知道自己有伤的,据说出赛之前打过止疼针,那么他为什么又要出赛呢?是侥幸心理还是明知不可为而为之呢?有或者其它的原因呢?令人深思!

2008.08.20
“阴谋论”

http://news.sina.com.cn/pl/2008-08-20/082616144905.shtml

哲 学家罗素说过:从虚假的前提出发,狗屁都可以推出来。只要精心选择证据以支持预设的立场,任何荒诞不经的结论,都可以让不具备分辨能力的人信服。如何炮制 一套完美的阴谋理论呢?英国《新科学家》周刊的建议是:选择你的对立面、选择你的事件、构造你的故事、准备你的辩护词——我认为这还缺一个最重要的建 议:选择一个信息不对称的环境。

2008-08-17

谋定而后动

Filed under: 随笔 — thomas @ 23:47

[2008.08.17 23:48]
谋定而后动,未定而不妄动。

[2008.08.20 20:09]
之前发生过若干次,考虑不周全而后采取补救,陷于被动境地的事情,其中大部分失败了,令人痛惜。究其原因,在于谋划失于周密,所以才有这样的感慨。

所谓谋,不是简单思考,不是思考某一件或一些事情,而是考虑所涉及的诸多因素、关节,策划方案,确立计划。对于复杂的事情来说,必有一个谋划的过程,涉及 的因素之多、变化之大、各种方展趋势、所有的可能结果,把这些问题考虑清楚,未雨绸缪。这才是谋划的价值与意义所在。

谋有不及。由于个人经验能力、社会历史条件所限,有一些因素难以顾及,或者能够预见却不确定是否能控制的情形也确实发生过,如此种种,所以从“谋”的层次是解决不了的。此时可决定不行动。然而若决定行动,则需防止不测,或准备随机应变。当然这也是谋定。

谋不能代替行,反之,行也不能代替谋。谋可见之事,备不时之变,此所谓谋定而后动。

行动是有代价的,需要消耗各种资源,包括时间,所以能够在谋的阶段解决的问题,应该考虑清楚,此所谓先谋而后行。

在一些情形需要根据形势的变化作出调整,甚至是方向的变化,执行时也需要对计划保持跟踪,动态评估。特别是执行遇阻,时过境迁,原来的目标,已经不能实现,此时应终止计划。

谋是一个过程,自然也有代价,只是比起行动的代价,明显要小。如果目标非常重要,因为害怕困难而畏缩不前,不足取。谋必须在有限的时间内完成,不能好谋无决,否则失去意义。所以仅仅是思考而不打算行动是错误的。

及时行动。客观形势在随时间变化,谋定后等待。一段时间后,原先的有利因素可能就不存在,甚至有可能出现不利的因素,这时候,原来的谋可能就不可行了。那就“白谋”了。

谋、行都需要努力!

2008-08-03

书评(2)-标题与内容

Filed under: 书评 — thomas @ 22:17

两种理解,一是讲解UML或者UML应用的书,而是讲解建模过程的书。

书评(1)-基本信息

Filed under: 书评 — thomas @ 20:26

UML 应用建模实践过程

【评 价】 (共 42 条) 参与评论
【作 者】尤克滨 [同作者作品]
【丛 书 名】 其他
【出 版 社】 机械工业出版社*     【书 号】 7111114361
【出版日期】 2003 年1月 【开 本】 16开 【页 码】 211     【版 次】1-1

基本信息除了,书名、作者、出版社、价格之外,还包括开本、版本、印次、字数,有的书籍比较详细,那么还会有作者简介、序言、导读之类的文字。比如说,该书是2003年1月1版1印,5000册,就是说这本在那次印刷中,共出了5000本。
按笔者个人的习惯,基本信息之外,先看书评,读者可以在china-pub读到比较多的书评,其它网站上就少的可怜了。

http://www.china-pub.com/member/bookpinglun/viewpinglun.asp?id=9053

书的质量是良莠不齐,读者的水平和品味也大不相同,那么对于读者的书评需要有自己的判断,当然必要的时候需要到书店里看看,部分章节后再做打算。对于笔者而言,计算机方面的书籍价格水平是比较高的,如果买一本书对自己没有什么帮助,那就不合算了。
有一点需要注意的,对别人有用的书,对自己未必能有很大帮助。后续将具体讨论这样的一些因素。

Powered by WordPress