您现在的位置: 天极网 > Win32多线程的性能(下)

Win32多线程的性能(下)

2000-08-14 00:00作者:-出处:逸仙时空责任编辑:
p>  界面(例如,需要添加一个“取消”按钮,并且依赖该计算结果的菜单项也不得不变灰)。

  

  除了性能、容量和快速响应之外,其他的一些原因也可能影响多线程设计。例如,

  在某些结构下,必需让计算以一种伪随机方式(脑海中再次出现的例子是Bolzmann 机器类型的神经网络,在这种网络中,仅当该网络中的每一个节点异步执行其计算时,

  该互联网络的预期行为才能够工作)。但是,在本文中,我将把讨论的范围限制在上面所涉及的三个因素,那就是:性能、容量和快速响应。

  测试的实现

  我曾经听说过许多关于抽象(abstraction)机制的讨论,说它封装了所有多线程的糟糕(nasty)方面到一个C++ 对象中,并且因此使一个应用程序获得了多线程的全部优点,而不是缺点。

  

  在本文中,我一开始就设计这样一个抽象。我将为一个C++的类ConcurrentExecution定义一个原型,该类将含有成员函数例如:DoConcurrent和DoSerial,并且这两个成员函数的参数将是一个普通对象数组和一个回调函数数组,

  这些回调函数将被每一个对象并发或串行地调用。该C++ 类将封装所有关于保持该线程和内部数据结构的真实(gory)细节。

  

  但是,对我来说,从一开始我就十分清楚,这样的一个抽象的用处十分有限,

  因为在设计一个多线程应用程序时的最大量的工作成了一个无法自动完成的任务,

  这个工作就是决定如何实现多线程。ConcurrentExecution 的第一个限制是回调函数将不允许显式或隐式的共享数据;或回调函数需要任何其他形式的同步操作,而这些同步操作将立刻牺牲掉所有该抽象所带来的优点,并且打开所有“精彩”的同步世界中的陷阱和圈套,例如死锁、竞争冲突、或需要非常复杂的复合同步对象。

  同样,也不允许那些可能潜在地被并发执行的计算来调用UI,因为就象我前面所讲到的,Win32 API对于调用UI 的线程强迫了许多个隐式的同步操作。请注意,还有许多其他的API 子集和库对于共享它们的线程强迫了隐式的同步操作。

  这些的限制使ConcurrentExecution 只具有极其有限的功能,说具体一点,就是一个管理纯粹工作者线程的抽象(完全独立的计算大多数情况下仅限于在非连续内存区域的数学计算)。

  然而,事实证明实现ConcurrentExecution 类并且在性能测试中使用它是非常有用的,因为,当我实现了该类,? 设计和运行了该测试之时,许多关于多线程的隐藏起来的细节都暴露出来了。请清楚以下一点,

  虽然ConcurrentExecution 类可以使多线程更容易处理,但是如果想要在商业产品中使用它,那么该类的实现还需要一些其他的工作。特别要提到的一点时,我忽略了所有的错误情况处理,这是不可忍受的。但是我假定只用于测试时(我明显地使用了ConcurrentExecution),错误不会出现。

  ConcurrentExecution类

  下面是ConcurrentExecution类的原型:

  class ConcurrentExecution

  {

  $#@60; private members omitted$#@62;

  public:

  ConcurrentExecution(int iMaxNumberOfThreads);

  ~ConcurrentExecution();

  int DoForAllObjects(int iNoOfObjects,long *ObjectArray,

  CONCURRENT_EXECUTION_ROUTINE pObjectProcessor,

  CONCURRENT_FINISHING_ROUTINE pObjectTerminated);

  BOOL DoSerial(int iNoOfObjects, long *ObjectArray,

  CONCURRENT_EXECUTION_ROUTINE pObjectProcessor,

  CONCURRENT_FINISHING_ROUTINE pObjectTerminated);

  };

  该类是从Thrdlib.dll库中导出的,而Thrdlib.dll库是示例测试套件THRDPERF 中的一个工程。在讨论该类的内部结构之前,让我们首先讨论成员函数的语义

  (semantics):

  ConcurrentExecution::ConcurrentExecution(int iMaxNumberOfThreads)

  {

  m_iMaxArraySize = min(iMaxNumberOfThreads, MAXIMUM_WAIT_OBJECTS);

  m_hThreadArray = (HANDLE *)VirtualAlloc(NULL,m_iMaxArraySize*sizeof(HANDLE),

  MEM_COMMIT,PAGE_READWRITE);

  m_hObjectArray = (DWORD *)VirtualAlloc(NULL,m_iMaxArraySize*sizeof(DWORD),

  MEM_COMMIT,PAGE_READWRITE);

  //当然,一个真正的实现必需在这里提供对错误的处理...

  };

  您可能会注意到构造函数ConcurrentExecution 有一个数字参数。该参数指定了该类的实例所支持的“并发的最大度数”;换句话说,

  如果某个ConcurrentExecution的实例被创建时,n 是它的一个参数,那么在任何给定的时间不能有超过n 个计算在执行。根据我们以前的分析,该参数就意味“无论有多少个顾客在等待,

  打开的结算柜台数不要多于n个”。

  int DoForAllObjects(int iNoOfObjects,long *ObjectArray,

  CONCURRENT_EXECUTION_ROUTINE pObjectProcessor,

  CONCURRENT_FINISHING_ROUTINE pObjectTerminated);

  这是在这里被实现的唯一有趣的成员函数。DoForAllObjects 的主要参数是一个对象的数组、一个处理器函数、和一个终结器函数。关于对象完全没有强制的格式;每次该处理器被调用时,将有一个对象被传递给它,而且完全由该处理器来解释对象。第一个参数iNoOfObjects,仅仅是要ConcurrentExecution 知道在对象数组中的元素数。请注意,在调用DoForAllObjects 时,如果对象数组的长度为1,那么它与调用CreateThread 就非常相似(有一点不同,那就是CreateThread不接受一个终结器参数)。

  

  DoForAllObjects 的语义如下:处理器将为每一个对象而调用。对象被处理的顺序并未指定;所有能够担保的只是每一个对象都将在某个时间被传递给处理器。并发的最大度数是由传递给ConcurrentExecution对象的构造函数的参数来决定的。

  

  处理器函数不能访问共享的数据,并且不能调用到UI 或做任何其他需要显式或隐式地串行操作的事情。目前,仅存在一个处理器函数能够对所有的对象工作;但是,要使用处理器数组来替代该处理器参数将是简单的。

  该处理器的原型如下:

  typedef DWORD (WINAPI *CONCURRENT_EXECUTION_ROUTINE)

  (LPVOID lpParameterBlock);

  当该处理器已经完成了在一个对象上的工作之后,终结器函数将立即被调用。与处理器不同,终结器函数是在该调用函数的环境中被串行调用的,并且可以调用所有的例程和访问调用程序所能够访问的所有数据。但是,应该要注意的是,终结器应该被尽可能地优化,因为终结器中的长计算会影响DoForAllObjects 的性能。请注意,尽管只要处理器结束了每一个对象终结器就会立即被调用,直到最后一个对象已经被终结之前,DoForAllObjects本身并没有返回。

  

  我们为什么要经历这么多使用终结器的痛苦?我们同样可以让每一个计算在处理器函数的最终结束时执行终结器代码,是吗?

  这样基本上是可以的;但是,有必要强调终结器是在调用DoForAllObjects的线程环境中被调用的。这样的设计使在每一个计算进入时处理它们的结果更加容易,而无须担心同步问题。

  终结器函数的原型如下:

  typedef DWORD (WINAPI *CONCURRENT_FINISHING_ROUTINE)

  (LPVOID lpParameterBlock,LPVOID lpResultCode);

  第一个参数是被处理的对象,第二个参数是处理器函数在该对象上的结果。

  

  DoForAllObjects的同类是DoSerial,DoSerial与DoForAllObjects 具有相同的参数列表,但是计算是被以串行的顺序处理的,并且以列表中的第一个对象开始。

相关文章及产品
关注此文读者还看过
相关

科技万花筒

文章排行
本周
本月
最近更新
关于我们|About us|网站律师|天极服务|电子杂志|RSS订阅|加入我们|网站地图
TMG
Copyright (C) 1999-2009 Chinabyte.com, All Rights Reserved 版权所有 天极网络
商务联系、网站内容、合作建议:010-82657868
版权声明 在线提交意见反馈 渝ICP证B2-20030003号
经营性网站备案信息 网警备案 中国网站排名
天极传媒:天极网|比特网|IT专家网|IT商网|52PK游戏网|IT分众