如何在多核多线程处理器设置并行线程,使程序并行运行

基于多核环境下的多线程并行程序设计方法研究
在过去十年里,随着众多领域并行计算需求的迅速增长而硬件又受到摩尔定律的严重制约,多核CPU现在被越来越多的应用于并行计算机中,于是基于多核处理器的并行程序设计技术也就成为了一种必然的发展趋势。此外,过去专用于图形处理的GPU也不再专用,因其具有大量的并行计算单元,使它在处理并行计算方面具有突出优势,正是其强大的并行计算能力引起了计算机科学家们的广泛关注,现在它几乎已不成文的成了重量级计算引擎的代名词。在经历了单核、多核的技术革新之后,异构计算正在成为当今打破并行计算程序性能瓶颈的又一突破技术,不同类型体系结构的设备都能被它有效地联系起来,实现协同工作,相互利用,一起完成程序计算。CUDA和OpenCL都是基于CPU+GPU模式的GPGPU异构计算,CUDA是NVIDIA提出的一种适用于通用并行计算的计算架构,而OpenCL则是一个专门为由CPU,GPU或其他体系结构类型的处理器组成的异构平台编写程序的框架。本文首先介绍了并行计算&
(本文共57页)
权威出处:
新型多核体系结构的出现及主流化,在满足用户对高性能及低功耗双重需求的同时,对并行程序设计研究也产生了重要的影响,带来了新的挑战。研发有效的方法与工具,支持程序设计人员开发与多核相适应的并行软件是目前多核并行编程领域面临的一个关键技术问题。围绕开发正确、高性能和可扩展多核应用程序这一目标,本文首先研究形式化开发多核应用程序的方法,借助Petri网直观的图形表现能力和严密的数学基础,通过定性分析被建模系统的动态行为以及定量计算被建模系统的各种性能指标,有效支持多核程序开发过程中的正确性验证和性能评价;其次,研究多核加速串行程序的方法,提出串行程序并行优化的一种解决思路,通过构造串行程序的程序依赖图,并将此程序依赖图转换为Petri网,借助Petri网丰富的模型分析方法挖掘串行程序内在的并行性,以打造出更多支持多线程并行运行的应用软件,更好地利用多核平台资源。本文主要研究成果包括:(1)面向多核多线程并行程序建模的需求,基于Petri...&
(本文共179页)
权威出处:
速度是计算机最基本的性能参数,致力于提高计算机性能的所有方法都是为了加快运算速度。多核系统为并行计算的研究及其实验提供了便利条件,已经成为系统架构设计中的主流。双核、四核乃至众核的集成促进了计算机系统性能的提升。然而,不断增加的计算核又带来了新的问题:计算核数目的线性增加能否带来性能的相应提高。在多核环境下,计算核利用率是提升计算机性能的因素之一。如果能考虑到充分利用每个核,将极大加快运算速度,提高系统性能。因此,充分挖掘每个核的潜力对并行计算的发展具有现实意义。鉴于此,本文对多年的TOP500(高性能计算机排名)的数据进行了分析,并从参数入手,围绕如何充分发挥每个核的作用、提高并行性进行了研究。本文的主要工作如下:(1)总结了现有计算机系统性能参数的选取和测试方法,分析了在多核系统环境下已有参数的片面性,定义并描述了反映核贡献率的计算机性能参数。(2)阐述了多核并行编程对于提高核贡献率和计算机程序运行速度的意义,分析了各种并行...&
(本文共60页)
权威出处:
人类对计算能力无休止的需求,以及并行计算领域两次重要的技术变革,使并行计算技术越来越受到人们的重视,尤其是通过各种互联技术连接在一起的分布式集群并行处理体系结构已经成为当今并行计算的主流。其中,一种特殊的结构是CMP-CLUSTER,即集群系统中单个计算节点是基于多个CMP芯片的共享存储多处理器并行系统,由于涉及到分布式存储和共享存储两种并行体系结构,我们称之为混合并行计算系统。并行编程难一直是阻碍并行计算广泛普及的主要原因,尤其是在CMP-CLUSTER这样的混合并行计算环境中存在多级并行化问题,即节点间并行、处理器芯片间并行、处理器芯片内多个核心并行,涉及到消息传递和共享变量两种并行编程模型,其编程难度更大。因此,如何为该混合并行计算环境提供特定的并行程序设计方法、编程模型、环境和工具来简化并行编程,是并行计算领域研究的热点和难点。本文正是在这种背景下展开了工作,所做的主要工作包括:系统地建立了CMP-CLUSTER混合并行...&
(本文共117页)
权威出处:
电力系统继电保护装置的整定计算需要通过仿真软件进行大批量轮断试验模拟各种运行方式,进而进行多次故障计算和定值计算来实现。随着电网复杂程度的上升,需要模拟的运行方式也越来越多,使得故障计算的工作量大幅增加,继电保护整定计算的发展遇到瓶颈。当代计算机与网络技术飞速发展,使得并行处理技术的运用变得更为广泛。为了提升电网故障计算的效率,本文研究了采用多种并行技术,实现电网故障计算的并行化。具体研究内容及成果如下:研究了使用Open MP(Open Multi-Processing)多线程并行技术进行多核并行故障计算程序的设计与仿真。利用多核计算机共享式存储的特点,将电网的初始信息预处理后存入共享内存中,由多线程同时获取任务信息,并行完成大批量故障计算的工作。通过对故障计算的部分变量进行线程私有化,削弱数据竞争带来的不良影响,保证多核并行故障计算的准确性。采用动态调度的方法对故障计算任务进行合理分配,使得各线程的负载均衡。设计了基于MPI...&
(本文共84页)
权威出处:
并行计算就是在并行计算机或分布式计算机等高性能计算系统上所做的超级计算,其物质基础是高性能并行计算机。为了能在高性能并行计算机上生成高速运行的并行代码,并行化编译技术的研究和发展同样成为计算机科学研究领域的一个热点。串行程序自动并行化是并行编译技术最重要的内容之一,它自动将串行程序转换为等价的能在并行计算机上高效运行的并行程序,并且能克服并行计算机编程困难、软件移植困难的不足,降低并行程序开发成本。本文针对在编译阶段实现串行程序自动并行化课题提出了一系列的并行处理方法。首先研究了自动并行化中的并行粒度,通过对三种并行粒度的分析提出了一种中粒度并行的实现方法,其中主要提出了中粒度并行时的基本块的并行识别方法和并行优化方法,解决了并行处理时并行线程工作量与线程开销之间的矛盾,避免了在并行处理时可能出现的程序执行效率降低的现象;其次,针对占串行程序计算量主体的循环的自动并行化进行了研究,并且提出了关于紧嵌套循环的自动并行化方法,为了解...&
(本文共119页)
权威出处:
扩展阅读:
CNKI手机学问
有学问,才够权威!
xuewen.cnki.net
出版:《中国学术期刊(光盘版)》电子杂志社有限公司
地址:北京清华大学 84-48信箱 大众知识服务
京ICP证040431号&
服务咨询:400-810--9993
订购咨询:400-819-9993
传真:010-关于多核多CPU多线程和并行计算的一点补充
多核多CPU多线程并行计算,在某些情况下的确是对性能有大幅提升。但问题是,对性能的提升并不是一定的。商家和技术提供者,为了自身的利益,很多情况下只展示了美好的一面,却把不利的一面加以隐藏。
线程的切换、调度,线程数据的同步,都须要消耗系统时间。线程越多,消耗越多。同时伴随引发的CPU的流水线清空,每次清空也将导致数十个时钟周期的浪费。虽然在以线程为单位进行调度的操作系统下,多线程能争取到更多的运行时间,但如果操作系统调度的单位是进程,而不是线程的话,多线程并不能争取到更多的运行时间,反而还会因进程内线程的调度而产生额外的消耗。
对于多核多CPU计算而言,先假设同一线程在同一时间片内只运行在一个Core上。那么,如果任线程在不同的Core上自由调度,则对每个Core有自己独立的L1、L2级缓存的CPU而言,对于某些任务线程,因为运行的Core变了,对应的L1、L2级缓存也同时变更,则如果上个时间片内的有效数据即使没有被换出L1或L2缓存,也不可以再加以利用,因为那些数据存在于另外一个Core的高速缓存中。于是高速缓存将需要重新加载。而在加载之前则得从另外一个Core的高速缓冲中重新将数据写回内存。因此,时间上的开销便出现了。相对而言,两个Core共享相同的高速缓存的CPU架构则没有这个问题。因此,如果因高速缓存频繁命中失败而导致的数据同步的时间开销相对于任务单元显著加大的话,则可以考虑将任务线程绑定单个Core运行。现在再假设,如果多核调度的策略是:同一线程的不同片断在同一时间片内可以运行在多个Core上。则如果线程编写不好,便会导致多个Core之间的数据同步。而如果数据同步处理不当,便会引发国企数据的使用,从而导致进一步的错误。
任何技术的采用,都得付出其相应的代价。因此,无论是多线程还是多核多CPU,无论是OpenMP还是CUDA,如果其带来的弊端大于其带来的好处,便需要仔细考虑一下,追赶时髦技术所付出的代价,是否值得。
没有更多推荐了,
不良信息举报
举报内容:
关于多核多CPU多线程和并行计算的一点补充
举报原因:
原文地址:
原因补充:
最多只允许输入30个字
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!如何在多核处理器设置并行线程,使程序并行运行。
[问题点数:20分,结帖人JinxLeader]
如何在多核处理器设置并行线程,使程序并行运行。
[问题点数:20分,结帖人JinxLeader]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
2014年 总版技术专家分年内排行榜第二
2013年 总版技术专家分年内排行榜第三
2015年9月 VC/MFC大版内专家分月排行榜第二2015年7月 硬件/嵌入开发大版内专家分月排行榜第二2014年5月 VC/MFC大版内专家分月排行榜第二2014年3月 VC/MFC大版内专家分月排行榜第二2013年10月 VB大版内专家分月排行榜第二2013年7月 VB大版内专家分月排行榜第二2012年5月 VB大版内专家分月排行榜第二2012年4月 VB大版内专家分月排行榜第二2012年2月 VB大版内专家分月排行榜第二2011年11月 VB大版内专家分月排行榜第二
2015年11月 VC/MFC大版内专家分月排行榜第三2015年6月 VC/MFC大版内专家分月排行榜第三2015年2月 VC/MFC大版内专家分月排行榜第三2014年1月 VC/MFC大版内专家分月排行榜第三2012年3月 VB大版内专家分月排行榜第三2011年12月 VB大版内专家分月排行榜第三2011年10月 VB大版内专家分月排行榜第三
匿名用户不能发表回复!|多核CPU上python多线程并行的一个假象(转) - pengyingh - 博客园
转自:http://www.cnblogs.com/skying555/p/6527189.html
GIL 与 Python 线程的纠葛
GIL 是什么东西?它对我们的 python 程序会产生什么样的影响?我们先来看一个问题。运行下面这段 python 程序,CPU 占用率是多少?
# 请勿在工作中模仿,危险:)
def dead_loop():
while True:
dead_loop()
答案是什么呢,占用 100% CPU?那是单核!还得是没有超线程的古董 CPU。在我的双核 CPU 上,这个死循环只会吃掉我一个核的工作负荷,也就是只占用 50% CPU。那如何能让它在双核机器上占用 100% 的 CPU 呢?答案很容易想到,用两个线程就行了,线程不正是并发分享 CPU 运算资源的吗。可惜答案虽然对了,但做起来可没那么简单。下面的程序在主线程之外又起了一个死循环的线程
import threading
def dead_loop():
while True:
# 新起一个死循环线程
t = threading.Thread(target=dead_loop)
# 主线程也进入死循环
dead_loop()
按道理它应该能做到占用两个核的 CPU 资源,可是实际运行情况却是没有什么改变,还是只占了 50% CPU 不到。这又是为什么呢?难道 python 线程不是操作系统的原生线程?打开 system monitor 一探究竟,这个占了 50% 的 python 进程确实是有两个线程在跑。那这两个死循环的线程为何不能占满双核 CPU 资源呢?其实幕后的黑手就是 GIL。
GIL 的迷思:痛并快乐着
GIL 的全称为&Global Interpreter Lock&,意即全局解释器锁。在 Python 语言的主流实现 CPython 中,GIL 是一个货真价实的全局线程锁,在解释器解释执行任何 Python 代码时,都需要先获得这把锁才行,在遇到 I/O 操作时会释放这把锁。如果是纯计算的程序,没有 I/O 操作,解释器会每隔 100 次操作就释放这把锁,让别的线程有机会执行(这个次数可以通过sys.setcheckinterval&来调整)。所以虽然 CPython 的线程库直接封装操作系统的原生线程,但 CPython 进程做为一个整体,同一时间只会有一个获得了 GIL 的线程在跑,其它的线程都处于等待状态等着 GIL 的释放。这也就解释了我们上面的实验结果:虽然有两个死循环的线程,而且有两个物理 CPU 内核,但因为 GIL 的限制,两个线程只是做着分时切换,总的 CPU 占用率还略低于 50%。
看起来 python 很不给力啊。GIL 直接导致 CPython 不能利用物理多核的性能加速运算。那为什么会有这样的设计呢?我猜想应该还是历史遗留问题。多核 CPU 在 1990 年代还属于类科幻,Guido van Rossum 在创造 python 的时候,也想不到他的语言有一天会被用到很可能 1000+ 个核的 CPU 上面,一个全局锁搞定多线程安全在那个时代应该是最简单经济的设计了。简单而又能满足需求,那就是合适的设计(对设计来说,应该只有合适与否,而没有好与不好)。怪只怪硬件的发展实在太快了,摩尔定律给软件业的红利这么快就要到头了。短短 20 年不到,代码工人就不能指望仅仅靠升级 CPU 就能让老软件跑的更快了。在多核时代,编程的免费午餐没有了。如果程序不能用并发挤干每个核的运算性能,那就意谓着会被淘汰。对软件如此,对语言也是一样。那 Python 的对策呢?
Python 的应对很简单,以不变应万变。在最新的 python 3 中依然有 GIL。之所以不去掉,原因嘛,不外以下几点:
欲练神功,挥刀自宫:
CPython 的 GIL 本意是用来保护所有全局的解释器和环境状态变量的。如果去掉 GIL,就需要多个更细粒度的锁对解释器的众多全局状态进行保护。或者采用 Lock-Free 算法。无论哪一种,要做到多线程安全都会比单使用 GIL 一个锁要难的多。而且改动的对象还是有 20 年历史的 CPython 代码树,更不论有这么多第三方的扩展也在依赖 GIL。对 Python 社区来说,这不异于挥刀自宫,重新来过。
就算自宫,也未必成功:
有位牛人曾经做了一个验证用的 CPython,将 GIL 去掉,加入了更多的细粒度锁。但是经过实际的测试,对单线程程序来说,这个版本有很大的性能下降,只有在利用的物理 CPU 超过一定数目后,才会比 GIL 版本的性能好。这也难怪。单线程本来就不需要什么锁。单就锁管理本身来说,锁 GIL 这个粗粒度的锁肯定比管理众多细粒度的锁要快的多。而现在绝大部分的 python 程序都是单线程的。再者,从需求来说,使用 python 绝不是因为看中它的运算性能。就算能利用多核,它的性能也不可能和 C/C++ 比肩。费了大力气把 GIL 拿掉,反而让大部分的程序都变慢了,这不是南辕北辙吗。
难道 Python 这么优秀的语言真的仅仅因为改动困难和意义不大就放弃多核时代了吗?其实,不做改动最最重要的原因还在于:不用自宫,也一样能成功!
那除了切掉 GIL 外,果然还有方法让 Python 在多核时代活的滋润?让我们回到本文最初的那个问题:如何能让这个死循环的 Python 脚本在双核机器上占用 100% 的 CPU?其实最简单的答案应该是:运行两个 python 死循环的程序!也就是说,用两个分别占满一个 CPU 内核的 python 进程来做到。确实,多进程也是利用多个 CPU 的好方法。只是进程间内存地址空间独立,互相协同通信要比多线程麻烦很多。有感于此,Python 在 2.6 里新引入了&multiprocessing这个多进程标准库,让多进程的 python 程序编写简化到类似多线程的程度,大大减轻了 GIL 带来的不能利用多核的尴尬。
这还只是一个方法,如果不想用多进程这样重量级的解决方案,还有个更彻底的方案,放弃 Python,改用 C/C++。当然,你也不用做的这么绝,只需要把关键部分用 C/C++ 写成 Python 扩展,其它部分还是用 Python 来写,让 Python 的归 Python,C 的归 C。一般计算密集性的程序都会用 C 代码编写并通过扩展的方式集成到 Python 脚本里(如 NumPy 模块)。在扩展里就完全可以用 C 创建原生线程,而且不用锁 GIL,充分利用 CPU 的计算资源了。不过,写 Python 扩展总是让人觉得很复杂。好在 Python 还有另一种与 C 模块进行互通的机制 : ctypes
利用 ctypes 绕过 GIL
ctypes 与 Python 扩展不同,它可以让 Python 直接调用任意的 C 动态库的导出函数。你所要做的只是用 ctypes 写些 python 代码即可。最酷的是,ctypes 会在调用 C 函数前释放 GIL。所以,我们可以通过 ctypes 和 C 动态库来让 python 充分利用物理内核的计算能力。让我们来实际验证一下,这次我们用 C 写一个死循环函数
void DeadLoop()
while (true);
用上面的 C 代码编译生成动态库&libdead_loop.so&(Windows 上是&dead_loop.dll)
,接着就要利用 ctypes 来在 python 里 load 这个动态库,分别在主线程和新建线程里调用其中的&DeadLoop
from ctypes import *
from threading import Thread
lib = cdll.LoadLibrary("libdead_loop.so")
t = Thread(target=lib.DeadLoop)
lib.DeadLoop()
这回再看看 system monitor,Python 解释器进程有两个线程在跑,而且双核 CPU 全被占满了,ctypes 确实很给力!需要提醒的是,GIL 是被 ctypes 在调用 C 函数前释放的。但是 Python 解释器还是会在执行任意一段 Python 代码时锁 GIL 的。如果你使用 Python 的代码做为 C 函数的 callback,那么只要 Python 的 callback 方法被执行时,GIL 还是会跳出来的。比如下面的例子:
typedef void Callback();
void Call(Callback* callback)
callback();
from ctypes import *
from threading import Thread
def dead_loop():
while True:
lib = cdll.LoadLibrary("libcall.so")
Callback = CFUNCTYPE(None)
callback = Callback(dead_loop)
t = Thread(target=lib.Call, args=(callback,))
lib.Call(callback)
注意这里与上个例子的不同之处,这次的死循环是发生在 Python 代码里 (DeadLoop&函数) 而 C 代码只是负责去调用这个 callback 而已。运行这个例子,你会发现 CPU 占用率还是只有 50% 不到。GIL 又起作用了。
其实,从上面的例子,我们还能看出 ctypes 的一个应用,那就是用 Python 写自动化测试用例,通过 ctypes 直接调用 C 模块的接口来对这个模块进行黑盒测试,哪怕是有关该模块 C 接口的多线程安全方面的测试,ctypes 也一样能做到。
虽然 CPython 的线程库封装了操作系统的原生线程,但却因为 GIL 的存在导致多线程不能利用多个 CPU 内核的计算能力。好在现在 Python 有了易经筋(multiprocessing), 吸星大法(C 语言扩展机制)和独孤九剑(ctypes),足以应付多核时代的挑战,GIL 切还是不切已经不重要了,不是吗。

我要回帖

更多关于 多核多线程 的文章

 

随机推荐