多线程级别的并行计算
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
多线程级别的并行计算
写多线程应用程序最困难的地方在于如何使各线程的工作协调进行。
Windows提供的用于线程间通信的各种机制是很容易掌握的,可是要把它们应用到工作中完成既定的功能时就会遇到这样、那样的困难。
对于常见的“生产者-消费者”模型,只要采取合理同步措施实现数据交换的统一性即可。
这类模型中的多线程往往任务独立,主要两类线程,一类写线程(生产者),一类读线程(消费者)。
但在实际应用中,多核机器往往需要使用多线
如何让多个处理器(多个线程)协作完成一项大规模的任务,涉及到任务的分解和调度。
因此,多核编程技术的关键问题在于如何将计算均匀分摊到各个CPU核上。
并行(Parallel)计算,即空间复用多个处理器,属于线程级别上的协作。
关于多线程协作,参阅王艳平著《Windows程序设计》第3章《Win32程序的执行单元》中的CRapidFinder例程。
该例程演示了如何使用多线程协助完成文件搜索任务。
多进程协助完成任务—分布式计算的滥觞
分布式计算则是进程级别上的协作,它是一种把需要进行大量计算的工程数据分割成小块,由多台计算机分别计算,在上传运算结果后再统一合并得出数据结论的技术。
现代大规模CG视觉特效的渲染系统有很多渲染节点组成,采用领先的分布式渲染技术,系统将自动确定网络中可用的渲染节点和资源,同时将将任务分解到相应渲染节点,自动负载平衡功能可以优化工作流程中每个渲染节点的使用效率。
从《后天》到《2012》,再到《阿凡达》,这些大电影,其数以PB计艰苦卓绝的渲染工作无不依赖于现代分布式集群工作站的协同作战。
线程的池化管理
通常情况下,内存的分配和释放通常都是mallloc和free显式进行的。
对同一块内存的多次释放通常会导致页面错误,而一直不释放又导致内存泄露,并且使系统性能大大下降。
频繁地创建和销毁内存资源是很耗时间的,因为创建一个对象要获取内存资源或者其它更多资源。
malloc/free操纵的是进程堆内存,C/C++运行库不允许两个线程同时从内存堆中分配内存,这种多线程同步操作也是相当耗时的。
对于共享资源,有一个很著名的设计模式:资源池(Resource Pool)。
该模式正是为了解决资源的频繁分配和释放所造成的问题。
如何利用已有对象来服务就是一个需要解决的关键问题,其实这就是一些“池化资源”技术产生的原因。
对于单核PC,多线程微观串行;对于多处理器系统,使用多线程技术可以充分发挥硬件的优势。
理论上,安装了N核CPU的PC,在某一时刻,系统底层所能并发执行的线程个数为N。
然而,线程的数量并不是多多益善。
首先,线程这种内核资源的创建和销毁本身就很耗系统资源;其次,频繁的线程上下文切换也会耗费较多的CPU时钟周期。
借鉴数据库连接池和内存池的池化管理思想,对于线程也可以实行池化管理。
在讨论WinSock的五种I/O模型中,选择模型(select、WSAAsyncSelcet、WSAEventSelect)基于消息轮询或事件等待,对于多用户并发响应往往为每个客户连接创建一个I/O伺服线程。
这种单连接单线程的处理方式,对于中小型服务器较为通用,但对大规模多用户的服务器的高并发需求无能为力。
完成端口模型本质上利用了Win32重叠I/O机制,底层利用完成端口队列对象来管理一个线程池。
关于线程池规模,根据经验为每个处理器创建2个线程,即工作线程数为
一个大规模高并发的服务器对于资源的管理至关重要,因此往往同时使用数据库连接池、内存池和线程池,对关键资源实行池化管理。
一般一个简单线程池至少包含下列组成部分。
线程池管理器(ThreadPoolManager):用于创建并管理线程池
工作线程(WorkThread):线程池中线程
任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行。
任务队列:用于存放没有处理的任务。
提供一种缓冲机制。
基于IOCP使用资源池化技术实现高性能的服务器,参阅王艳平、张越著《Windows网络与通信程序设计》第4章《IOCP与可伸缩网络程序》中的
CIOCPServer系统结构图
参考:
《线程池的介绍及简单实现》
《深入研究线程池》
《一个C++多线程程序开发库》
《一个boost底下的线程池》。