Python 是解釋型的語言,而 Python 解釋器使用 GIL(全局解 釋器鎖)來在內(nèi)部禁止并行執(zhí)行,正是這個(gè) GIL 限制你在多核處理器上同一時(shí)間也只能執(zhí)行一條字節(jié)碼指令. 聽朋友說 python 3.0 里面已經(jīng)改進(jìn), 默認(rèn)有了多處理器編程的庫了. Python2.XX 暫時(shí)還不支持。
Parallel Python 這個(gè)庫,正是為支持 smp 多路多核多 cpu 而設(shè)計(jì)的, 而且它不僅可以多核處理器協(xié)同工作,還可以通過網(wǎng)絡(luò)集群運(yùn)行。
官網(wǎng):
http://www.parallelpython.com/
PP 是一個(gè) Python 模塊,提供了在 SMP(多 CPU 或多核)和集群(通過網(wǎng)絡(luò)連接的多臺計(jì)算機(jī))上并行執(zhí)行 Python 代碼的機(jī)制。輕量級,易于安裝,并 集成了其他軟件。PP 也是一個(gè)用純 Python 代碼實(shí)現(xiàn)的跨平臺,開放源碼模塊。
有些朋友可能對并發(fā)和并行理解有點(diǎn)亂,在這里梳理下哈:
當(dāng)有多個(gè)線程在操作時(shí),如果系統(tǒng)只有一個(gè) CPU,則它根本不可能真正同時(shí)進(jìn)行一個(gè)以上的線程,它只能把 CPU 運(yùn)行時(shí)間劃分成若干個(gè)時(shí)間段,再將時(shí)間 段分配給各個(gè)線程執(zhí)行,在一個(gè)時(shí)間段的線程代碼運(yùn)行時(shí),其它線程處于掛起狀態(tài).這種方式我們稱之為并發(fā)(Concurrent).
當(dāng)系統(tǒng)有一個(gè)以上 CPU 時(shí),則線程的操作有可能非并發(fā).當(dāng)一個(gè) CPU 執(zhí)行一個(gè)線程時(shí),另一個(gè) CPU 可以執(zhí)行另一個(gè)線程,兩個(gè)線程互不搶占 CPU 資源,可以同時(shí)進(jìn)行,這種方式我們稱之為并行(Parallel)
地址:http://rfyiamcool.blog.51cto.com/1030776/1357112
在并發(fā)環(huán)境時(shí),多線程不可能真正充分利用 CPU,節(jié)約運(yùn)行時(shí)間,它只是以”掛起->執(zhí)行->掛起”的方式以很小的時(shí)間片分別運(yùn)行各個(gè)線程,給用戶以每個(gè)線程都在運(yùn)行的錯(cuò)覺.在這種環(huán)境中,多線程程序真正改善的是系統(tǒng)的響應(yīng)性能和程序的友好性.
在并行環(huán)境中, 一個(gè)時(shí)刻允許多個(gè)線程運(yùn)行,這時(shí)多線程程序才真正充分利用了多 CPU 的處理能力, 節(jié)省了整體的運(yùn)行時(shí)間.在這種環(huán)境中,多線程程序能體現(xiàn)出它的四大優(yōu)勢:充分利用 CPU,節(jié)省時(shí)間,改善響應(yīng)和增加程序的友好性.
并發(fā)和并行的區(qū)別就是一個(gè)處理器同時(shí)處理多個(gè)任務(wù)和多個(gè)處理器或者是多核的處理器同時(shí)處理多個(gè)不同的任務(wù)。
前者是邏輯上的同時(shí)發(fā)生(simultaneous),而后者是物理上的同時(shí)發(fā)生.
來個(gè)比喻:并發(fā)和并行的區(qū)別就是一個(gè)人同時(shí)吃三個(gè)饅頭和三個(gè)人同時(shí)吃三個(gè)饅頭。
咱們跑一下:
安裝 pp 模塊
http://wiki.jikexueyuan.com/project/python-actual-combat/images/77.jpg" alt="pic" />
好,測試
【這是單核的利用情況下】
http://wiki.jikexueyuan.com/project/python-actual-combat/images/78.jpg" alt="pic" />
開啟 python 多核的情況下
【看到?jīng)]有,多出了 4 個(gè)進(jìn)程,這四個(gè)進(jìn)程是綁在不同的 cpu上,這四個(gè) cpu 跑的很均勻】
http://wiki.jikexueyuan.com/project/python-actual-combat/images/79.jpg" alt="pic" />
測試的代碼:
#-*- coding: UTF-8 -*-
import math, sys, time
import pp
def IsPrime(n):
"""返回 n 是否是素?cái)?shù)"""
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):
for i in xrange(15):
sum([x for x in xrange(2,n) if IsPrime(x)])
"""計(jì)算從 2-n 之間的所有素?cái)?shù)之和"""
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 '單線程執(zhí)行,總耗時(shí)', 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 可以用的工作核心線程數(shù)", 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 "多線程下執(zhí)行耗時(shí): ", time.time() - start_time, "s"
job_server.print_stats()
pp 的官方例子給的很足,也相當(dāng)?shù)暮喚殻?/p>
導(dǎo)入讓 python 支持多核心的模塊
1) Import pp module:
import pp
一個(gè)實(shí)例,含有cpu的核心數(shù)目 2) Start pp execution server with the number of workers set to the number of processors in the system
job_server = pp.Server()
可以支持網(wǎng)絡(luò)的分布式運(yùn)算!
# tuple of all parallel python servers to connect with
ppservers = ()
#ppservers = ("10.0.0.1",)
ncpus = int(sys.argv[1])
# Creates jobserver with ncpus workers
job_server = pp.Server(ncpus, ppservers=ppservers)
3) Submit all the tasks for parallel execution:
f1 = job_server.submit(func1, args1, depfuncs1, modules1)
f2 = job_server.submit(func1, args2, depfuncs1, modules1)
f3 = job_server.submit(func2, args3, depfuncs2, modules2)
...etc...
4) Retrieve the results as needed:
r1 = f1()
r2 = f2()
r3 = f3()
...etc...
剛才說了 parallet python 是支持網(wǎng)絡(luò)的分布式運(yùn)算集群的!
Advanced guide, clusters
On the nodes
1) Start parallel python execution server on all your remote computational nodes (listen to a given port 35000, and local network interface only, accept only connections which know correct secret):
node-1> ./ppserver.py -p 35000 -i 192.168.0.101 -s "mysecret"
node-2> ./ppserver.py -p 35000 -i 192.168.0.102 -s "mysecret"
node-3> ./ppserver.py -p 35000 -i 192.168.0.103 -s "mysecret"
On the client
2) Import pp module:
import pp
3) Create a list of all the nodes in your cluster (computers where you've run ppserver.py)
ppservers=("node-1:35000", "node-2:35000", "node-3:35000")
4) Start pp execution server with the number of workers set to the number of processors in the system, list of ppservers to connect with and secret key to authorize the connection:
job_server = pp.Server(ppservers=ppservers, secret="mysecret")
5) Submit all the tasks for parallel execution:
f1 = job_server.submit(func1, args1, depfuncs1, modules1)
f2 = job_server.submit(func1, args2, depfuncs1, modules1)
f3 = job_server.submit(func2, args3, depfuncs2, modules2) ...etc...
6) Retrieve the results as needed:
r1 = f1()
r2 = f2()
r3 = f3()
...etc...
7) Print the execution statistics:
job_server.print_stats()
http://wiki.jikexueyuan.com/project/python-actual-combat/images/80.jpg" alt="pic" />
地址:http://rfyiamcool.blog.51cto.com/1030776/1357112
這里有很多的例子,大家可以跑跑!
http://www.parallelpython.com/content/view/17/31/
安裝 python 的 pp 模塊直接運(yùn)行就行
本文出自 “峰云,就她了。” 博客,謝絕轉(zhuǎn)載!