讀古今文學網 > Python實戰-從菜鳥到大牛的進階之路 > 25 Parallel Python 實現程序的並行多 cpu 多核利用【pp 模塊】 >

25 Parallel Python 實現程序的並行多 cpu 多核利用【pp 模塊】

 為啥要這個模塊:

Python 是解釋型的語言,而 Python 解釋器使用 GIL(全局解 釋器鎖)來在內部禁止並行執行,正是這個 GIL 限制你在多核處理器上同一時間也只能執行一條字節碼指令. 聽朋友說 python 3.0 裡面已經改進, 默認有了多處理器編程的庫了. Python2.XX 暫時還不支持。

Parallel Python 這個庫,正是為支持 smp 多路多核多 cpu 而設計的, 而且它不僅可以多核處理器協同工作,還可以通過網絡集群運行。

官網:
http://www.parallelpython.com/

pp 模塊的簡介

PP 是一個 Python 模塊,提供了在 SMP(多 CPU 或多核)和集群(通過網絡連接的多台計算機)上並行執行 Python 代碼的機制。輕量級,易於安裝,並 集成了其他軟件。PP 也是一個用純 Python 代碼實現的跨平台,開放源碼模塊。

下面是看起來很高端的功能介紹!

  • 在 SMP 和集群上並行執行 Python 代碼
  • 易於理解和實現的基於工作的並行機制,便於把穿行應用轉換成並行的
  • 自動構造最佳配置(默認時工作進程數量等同於系統處理器數量)
  • 動態處理器分配(允許運行時改變工作處理器數量)
  • 函數的工作緩存(透明的緩存機制確保後續調用降低負載)
  • 動態負載均衡(任務被動態的分配到各個處理器上)
  • 基於 SHA 的連接加密認證
  • 跨平台移植(Windows/Linux/Unix)
  • 開放源代碼

有些朋友可能對並發和並行理解有點亂,在這裡梳理下哈:

當有多個線程在操作時,如果系統只有一個 CPU,則它根本不可能真正同時進行一個以上的線程,它只能把 CPU 運行時間劃分成若干個時間段,再將時間 段分配給各個線程執行,在一個時間段的線程代碼運行時,其它線程處於掛起狀態.這種方式我們稱之為並發(Concurrent).
當系統有一個以上 CPU 時,則線程的操作有可能非並發.當一個 CPU 執行一個線程時,另一個 CPU 可以執行另一個線程,兩個線程互不搶佔 CPU 資源,可以同時進行,這種方式我們稱之為並行(Parallel)

地址:http://rfyiamcool.blog.51cto.com/1030776/1357112

多線程在並發和並行環境中的不同作用

在並發環境時,多線程不可能真正充分利用 CPU,節約運行時間,它只是以」掛起->執行->掛起」的方式以很小的時間片分別運行各個線程,給用戶以每個線程都在運行的錯覺.在這種環境中,多線程程序真正改善的是系統的響應性能和程序的友好性.
在並行環境中, 一個時刻允許多個線程運行,這時多線程程序才真正充分利用了多 CPU 的處理能力, 節省了整體的運行時間.在這種環境中,多線程程序能體現出它的四大優勢:充分利用 CPU,節省時間,改善響應和增加程序的友好性.

並發和並行的區別就是一個處理器同時處理多個任務和多個處理器或者是多核的處理器同時處理多個不同的任務。

前者是邏輯上的同時發生(simultaneous),而後者是物理上的同時發生.

來個比喻:並發和並行的區別就是一個人同時吃三個饅頭和三個人同時吃三個饅頭。

咱們跑一下:

安裝 pp 模塊

圖片 25.1 pic

好,測試

【這是單核的利用情況下】

圖片 25.2 pic

開啟 python 多核的情況下

【看到沒有,多出了 4 個進程,這四個進程是綁在不同的 cpu上,這四個 cpu 跑的很均勻】

圖片 25.3 pic

測試的代碼:

 #-*- coding: UTF-8 -*-import math, sys, timeimport ppdef 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 Falsei += 1    return Truedef SumPrimes(n):    for i in xrange(15):sum([x for x in xrange(2,n) if IsPrime(x)])    """計算從 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.timefor input in inputs:    print SumPrimes(input)print \'單線程執行,總耗時\', time.time - start_time, \'s\' # tuple of all parallel python servers to connect withppservers =  #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.timejobs = [(input, job_server.submit(SumPrimes,(input,), (IsPrime,), ("math",))) for input in inputs]for input, job in jobs:    print "Sum of primes below", input, "is", jobprint "多線程下執行耗時: ", time.time - start_time, "s"job_server.print_stats 

pp 的官方例子給的很足,也相當的簡練!

導入讓 python 支持多核心的模塊

1) Import pp module:

import pp

一個實例,含有cpu的核心數目2) Start pp execution server with the number of workers set to the number of processors in the system

job_server = pp.Server

可以支持網絡的分佈式運算!

 # tuple of all parallel python servers to connect withppservers =  #ppservers = ("10.0.0.1",)ncpus = int(sys.argv[1]) # Creates jobserver with ncpus workersjob_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 是支持網絡的分佈式運算集群的!

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

圖片 25.4 pic

地址:http://rfyiamcool.blog.51cto.com/1030776/1357112

這裡有很多的例子,大家可以跑跑!

http://www.parallelpython.com/content/view/17/31/

安裝 python 的 pp 模塊直接運行就行

本文出自 「峰雲,就她了。」 博客,謝絕轉載!