Parallel Python 并行开发多核心并行程序
python是解释型的语言,而Python解释器使用GIL(全局解 释器锁)来在内部禁止并行执行,正是这个GIL限制你在多核处理器上同一时间也只能执行一条字节码指令. python 3.0 里面已经改进, 默认有了多处理器编程的库了. Python2.XX暂时还不支持。
Parallel Python 这个库,正是为次设计的, 而且它不仅可以多核处理器协同工作,还可以通过网络集群运行。
http://www.parallelpython.com/
下面的中文介绍来自这里:
1. 简介
PP 是一个Python模块,提供了在SMP(多CPU或多核)和集群(通过网络连接的多台计算机)上并行执行Python代码的机制。轻量级,易于安装,并 集成了其他软件。PP也是一个用纯Python代码实现的跨平台,开放源码模块。
2. 功能
* 在SMP和集群上并行执行Python代码
* 易于理解和实现的基于工作的并行机制,便于把穿行应用转换成并行的
* 自动构造最佳配置(默认时工作进程数量等同于系统处理器数量)
* 动态处理器分配(允许运行时改变工作处理器数量)
* 函数的工作缓存(透明的缓存机制确保后续调用降低负载)
* 动态负载均衡(任务被动态的分配到各个处理器上)
* 基于SHA的连接加密认证
* 跨平台移植(Windows/Linux/Unix)
* 开放源代码
3. 开发动机
现代Python程序已经广泛的应用在商业逻辑,数据分析和科学计算等方面。其中广泛应用着SMP(多处理器或多核)和集群(通过网络连接的多台计 算机),市场需要并行的执行的Python代码。
在SMP计算机上编写并行程序最简单的方法是使用多线程。尽管如此,使用 ‘thread’ 和 ‘threading’ 模块仍然无法在字节码一级实现并行。因为Python解释器使用GIL(全局解释器锁)来在内部禁止并行执行。这个GIL限制你在SMP机器上同一时间也 只能执行一条字节码指令。
PP 模块正是为了解决这个问题而来,提供简单的方式实现并行Python应用。 ppsmp 在内部使用 进程 和 IPC (进程间通信)来组织并行计算。并处理了所有内部的细节和复杂性,你的应用程序只需要提交工作任务并取回结果就可以了。这也是编写并行程序的最简单的方 法。
为了更好的实现,所有使用 PP 的软件通过网络来连接和协作。跨平台和动态负载均衡使得 PP 可以轻松组织多平台、异构的集群计算环境。
以官方例子:
#-*- coding: UTF-8 -*- #------------------------------------------------------------------------------- # Name: # Purpose: # # Author: ankier # # Created: 05-02-2013 # Copyright: (c) ankier 2013 # Licence: <your licence> #------------------------------------------------------------------------------- import math, sys, time import pp def IsPrime(n): """返回n是否是素数""" if not isinstance(n, int): raise TypeError("argument passed to is_prime is not of 'int' type") if n < 2: return False if n == 2: return True max = int(math.ceil(math.sqrt(n))) i = 2 while i <= max: if n % i == 0: return False i += 1 return True def SumPrimes(n): """计算从2-n之间的所有素数之和""" return sum([x for x in xrange(2,n) if IsPrime(x)]) inputs = (100000, 100100, 100200, 100300, 100400, 100500, 100600, 100700) start_time = time.time() for input in inputs: print SumPrimes(input) print '单线程执行,总耗时', time.time() - start_time, 's' # tuple of all parallel python servers to connect with ppservers = () #ppservers = ("10.0.0.1",) if len(sys.argv) > 1: ncpus = int(sys.argv[1]) # Creates jobserver with ncpus workers job_server = pp.Server(ncpus, ppservers=ppservers) else: # Creates jobserver with automatically detected number of workers job_server = pp.Server(ppservers=ppservers) print "pp 可以用的工作核心线程数", job_server.get_ncpus(), "workers" start_time = time.time() jobs = [(input, job_server.submit(SumPrimes,(input,), (IsPrime,), ("math",))) for input in inputs] for input, job in jobs: print "Sum of primes below", input, "is", job() print "多线程下执行耗时: ", time.time() - start_time, "s" job_server.print_stats()
运行结果:
454396537 454996777 455898156 456700218 457603451 458407033 459412387 460217613 单线程执行,总耗时 3.15899991989 s pp 可以用的工作核心线程数 4 workers Sum of primes below 100000 is 454396537 Sum of primes below 100100 is 454996777 Sum of primes below 100200 is 455898156 Sum of primes below 100300 is 456700218 Sum of primes below 100400 is 457603451 Sum of primes below 100500 is 458407033 Sum of primes below 100600 is 459412387 Sum of primes below 100700 is 460217613 多线程下执行耗时: 1.44400000572 s Job execution statistics: job count | % of all jobs | job time sum | time per job | job server 8 | 100.00 | 5.2460 | 0.655750 | local Time elapsed since server creation 1.44400000572 0 active tasks, 4 cores