分类: C/C++
2013-08-25 09:58:14
原文地址:C++ 并行编程的一些总结 作者:gogozhaoxinfeng
2009-2010年,参加了一些服务器软件的开发,在经历了很多困难后, 终于有了一些心得。并发、分布式是比较大的话题了,也是我最感兴趣的技术之一了。现在我能从事并发与分布式的编程开发,还是比较开心的。
在计算机相关书籍中,我印象最深的就是《GoF》 ,当我读了《GoF》后才知道什么叫程序设计,什么叫面向对象,才知道什么是设计模式。自从把设计模式应用到软件开发中,软件的设计就一下子简单起来。比如应用最多的就是策略模式。如果不使用策略模式,c++的多态几乎毫无用处。于是做了一阵服务器程序后,我就思考为什么并行程序这么复杂,为什么并行程序充满陷阱,为什么并行程序的测试总是不够完美。有没有一些设计模式可以应用到并行编程中,能够使其设计、开发、测试变得轻松一些。还有一点的是,开发并行程序不是吃饱撑的,而是为了调高软件性能,那么不行程序的性能测试也是非常重要的。因为业界有句很流行的话,叫不要自以为的去优化程序,只能用数据来说话。
什么是并发, 简单而言就是在同一段时间内两个或多个任务同时执行。使用并发编程的理由是:
1. 并发程序可以执行的更快;比如算法如排序等,通过并发可以更快的完成运算。
2. 并发可以提高吞吐量;比如Apache+php,Apache接受client的连接,将请求交给php处理,每个php进程独立的处理请求并返回结果。这样多个client端看起来服务器能够并行的处理请求。当然若php进程无法及时处理到来的请求,那么可能前台将受到502错误了。
3. 并发可以调高用户体验;比如GUI程序中,单独的线程处理用户的行为事件如鼠标单击,真正的IO/运算则交给后台进程运行,使得用户永远感觉软件是立即响应的。若后台线程实在耗时,那么可以通过展示Loading界面等方式,告知用户等待。
4. 模块化;我们常常把相对独立的逻辑设计成为一个模块,各个模块可以并行执行,其实有时这种逻辑更加符合现实世界的模型。
5. 以上优点兼而有之;那就是分布式程序;而且分布式程序能够更好的处理局部软件失效的情况。当有海量数据需要处理时,分布式就会无可避免。
6. 其他;….
在大学时,教科书中把并行计算分为SPMD(单程序流多数据流)和MPMD(多程序流多数据流)。那是对这些概念真是一头雾水,如今看来还真是精辟。在SPMD中,典型的应用就是web server如Apache + php,php都是相同的程序代码,但执行的数据即请求不同。而MPMD中一个问题被分成多个方面,每个方面被不同的程序并行解决,分布式的程序一般都是MPMD模型。
在我们的程序中个,并发发生在:
1. 程序指令并发;处理器可以一条指令执行多个运算。一般这些对c++程序员是不可见的,一般由编译器默默完成,属于指令级别并发。
2. 函数级并发。在结构化编程中,一个函数往往代表一段逻辑的处理过程,通过将这样的函数并行运行,达到并行解决问题的目的。POSIX thread 的API 就是接受一个(void* fun)(void*)的函数指针。
3. 对象级并发;我们开发服务器软件的时候,并不是显示的设计并发,而是将各个模块抽象成对象,然后向各个对象post任务,每个对象自己决定线性运行还是并发执行。一般这样的对象我们称之为service,内部通过使用boost::thread创建线程。
4. 应用程序级并发;分布式的并发程序组成集群,实现了更高级别的并发。
并发实例探讨:
1. Logic_Server; 此server是并发集群中的一个Node,他通过TCP与其他Node 进行通信。接受请求并交给Python处理,并将Python处理的结果返回给其他Node,我们的Logic_Server跟Apache + Php非常的相像.
2. Task_Server; 此 server 为user生成task,对用户行为进行统计,task完成时为user生成新的task,当task定义被更新时,task的生成策略应立即被fresh。所以Task_server 拥有唯一的一份task生成策略,统计用户行为的逻辑是并行的,建立一个线程池,通过将用户mod uid的方式均衡负载到各个线程,单个用户的逻辑是串行的,但是多个用户的运算确是并行的,互不干扰。
并行编程中现在感觉比较棘手的问题是测试,尤其是采用异步的方式实现并发时候,其测试更是让人头疼不已。如何才能有效的测试并行程序,希望能找到更好更简洁更有效的方式。