有关对耗时很大循环进行并行化优化的探讨 之一:并发搜索的处理
来源:互联网 发布:早期复极综合征知乎 编辑:程序博客网 时间:2024/05/29 14:33
在对程序优化过程中,我们往往对循环体有着刻骨的仇恨,因为它对性能的损耗尤其之大,比如如下例程,是个简单的循环例程,全部执行需要30秒以上(痛苦):
public enum HandleRst
{
完成,
错误_手术刀忘肚子里了,
失败_药物过敏,
失败_家属不签字,
}
public class Obj_Fath
{
private int _SonLen;
public int SonLen
{
get { return _SonLen; }
set { _SonLen = value; }
}
public Obj_Fath(string myt)
{
_T = myt;
_SonObjList = new List<Obj_Son>();
for (int i = 0; i < 1500; i++)
{
Obj_Son p = new Obj_Son(this );
_SonObjList.Add(p);
}
}
public HandleRst DoAsyncHandle()
{
HandleRst rst= HandleRst.完成;
if (_SonObjList.Count > 0)
{
foreach (Obj_Son son in _SonObjList)
{
HandleRst r = ComputeEachSon(son);
if (r != HandleRst.完成)
{
_ThisHandleRst = r;
break;
}
}
}
return rst ;
}
HandleRst ComputeEachSon(Obj_Son sonObj)
{
Thread.Sleep(1);
return sonObj.DoCompute();
}
}
public class Obj_Son
{
Obj_Fath _ObjFath;
public Obj_Son(Obj_Fath fathObj)
{
_ObjFath = fathObj;
}
public HandleRst DoCompute()
{
int len=0;
lock (_ObjFath )
{
_ObjFath.SonLen++;
len =_ObjFath .SonLen ;
}
Thread.Sleep (1);
if (len >1300)
{
return HandleRst.失败_家属不签字;
}
return HandleRst.完成;
}
}
但如何优化它呢,我们很容易想到要对循环体进行并发执行,即
foreach (Obj_Son son in _SonObjList)
{
Thread t =new Thread(ParameterThreadStart(ThreadCompute));
t.Start(son);
}
但这里带来了几个问题:
1) 如何获得ComputeEachSon方法的结果?
2) 如何在返回不为“完成”时立即退出循环?
貌似使用简单的多线程并发无法解决这个问题。
于是,我们想到了采用异步方法,改进后,执行的时间缩减到了6秒,效果还是不错的,附上简单的异步处理代码供大家研究改进。
bool _Tok;
ManualResetEvent _FinEvent;
private HandleRst _ThisHandleRst;
private int _HandleCount;
public HandleRst DoAsyncHandle()
{
_ThisHandleRst = HandleRst.完成;
_FinEvent = new ManualResetEvent(false);
_HandleCount = 0;
if (_SonObjList.Count > 0)
{
foreach (Obj_Son son in _SonObjList)
{
if (_Tok)
break;
HasSonComputingHandler h = new HasSonComputingHandler(ComputeEachSon);
HandleRst r = HandleRst.完成;
AsyncCallback t = new AsyncCallback(HandleCallBack);
h.BeginInvoke(son, t, h);
}
_FinEvent.WaitOne();
}
return _ThisHandleRst ;
}
void HandleCallBack(IAsyncResult iR)
{
if (_Tok)
return;
HasSonComputingHandler u = (HasSonComputingHandler)iR.AsyncState;
HandleRst r = u.EndInvoke(iR);
lock (this)
{
if (r != HandleRst.完成)
{
_ThisHandleRst = r;
_FinEvent.Set();
_Tok = true;
}
_HandleCount++;
if (_HandleCount == _SonObjList.Count)
{
_ThisHandleRst = r;
_FinEvent.Set();
_Tok = true;
}
}
}
试了一下异步操作循环体,发现了一个有趣的现象:
执行
Obj_Fath t = new Obj_Fath("hello");
HandleRst u= t.DoAsyncHandle();
MessageBox.Show("\n计数HandleCount:" +t.HandleCount .ToString ()+"\n计数Sonlen:"+t.SonLen .ToString () +"\n" );
发现 HandeCount值在1298~1302之间
SonLen值在1306~1312之间。
如果顺序执行循环体,程序是在1300次循环时退出, 这说明
1)程序注册了2500个异步委托后,就直接进入阻塞等待状态。
2)完成退出当前方法后,未执行的异步委托会自动取消委托。
这样的话比起线程来说,就有很多好处了,因为发出线程是很难取消的。
更多请看
有关对耗时很大循环进行并行化优化的探讨之二:多重循环任务的并发处理 .
- 有关对耗时很大循环进行并行化优化的探讨 之一:并发搜索的处理
- 有关对耗时很大循环进行并行化优化的探讨之二:多重循环任务的并发处理
- 有关对耗时很大循环进行并行化优化的探讨之三:并行线程越多运行就会越快吗?
- 有关并发和并行的问题解析
- iOS对耗时操作的处理方法
- openMP之一简单的并行循环
- 处理大并发之一 对异步非阻塞的理解
- 处理大并发之一 对异步非阻塞的理解
- 处理大并发之一 对异步非阻塞的理解
- 处理大并发之一 对异步非阻塞的理解
- 处理大并发之一 对异步非阻塞的理解
- 处理大并发之一 对异步非阻塞的理解
- 处理大并发之一 对异步非阻塞的理解
- 处理大并发之一 对异步非阻塞的理解
- 处理大并发之一 对异步非阻塞的理解
- 处理大并发之一 对异步非阻塞的理解
- 处理大并发之一 对异步非阻塞的理解
- 处理大并发之一 对异步非阻塞的理解
- 设计模式之四 --- 建造(Builder)模式
- 技术创业公司,技术团队一定要有一个强者坐镇,否则失败率极高
- C++程序内存布局
- 设计模式之五 --- 代理(Proxy)模式
- 移植Uboot-2010.06到TQ2440开发板详解之三
- 有关对耗时很大循环进行并行化优化的探讨 之一:并发搜索的处理
- Linux的三种线程实现模型漫谈
- 继承与派生——虚基类
- 编写安全代码——不要用memcmp比较structure
- lib和dll的关系
- chown更改文件和目录的所有者
- 打开、关闭、创建 数据库 -sqlite 基础教程(4)
- GBK与UTF-8之间的转换
- JAVA帮助文档全系列