[英]Use cases of parallel programming using multiprocessing module in python
[英]Python Multiprocessing of parallel cases
我有一組模擬,每個模擬都使用MPI並行運行(它們是CFD模擬)。 但是,我想在Python中創建一個任務池並並行運行。 我使用了以下多重處理庫:
import itertools
import multiprocessing
def Run_Cases(params):
run_each_mpi_simulation
a = range(1,len(U)); b = range(len(R))
paramlist = list(itertools.product(a,b))
pool = multiprocessing.Pool()
pool.map(Run_Case,paramlist)
因此,基本上,代碼創建了任務池(模擬實例)並將其分配給每個要運行的處理器。 但是,由於每種情況都是並行(MPI)模擬,因此沒有考慮每個模擬需要2個處理器。 這會導致仿真性能顯着下降。
因此,我想知道是否可以通過某種方式定義在Python多處理程序包中分配給每個任務的處理器數量?
任何意見,高度贊賞。
親切的問候阿什坎
編輯/ UPDATE:
非常感謝@AntiMatterDynamite的回答。
我嘗試了您的方法,並且處理器上的性能和工作負荷分配得到了很大改善,但似乎存在兩個問題:
1)盡管一切仍在進行,但我收到以下消息
Exception in thread Thread-2:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 1073, in run
self.function(*self.args, **self.kwargs)
File "/usr/local/lib/python2.7/dist-packages/PyFoam/Execution/FoamThread.py", line 86, in getLinuxMem
me=psutil.Process(thrd.threadPid)
File "/usr/local/lib/python2.7/dist-packages/psutil/__init__.py", line 341, in __init__
self._init(pid)
File "/usr/local/lib/python2.7/dist-packages/psutil/__init__.py", line 381, in _init
raise NoSuchProcess(pid, None, msg)
NoSuchProcess: psutil.NoSuchProcess no process found with pid 8880
非常感謝您的評論。
再次非常感謝Ashkan
編輯/ UPDATE:
我相信該消息是因為進程數量少於處理器列表。 因為我有兩個案例/模擬,每個案例/模擬都使用2個處理器,所以當我使用超線程時,我有8個處理器,因此得到了消息。 它使用4個處理器或具有更大的仿真池來解決。
multiprocessing.Pool
接受要創建的進程數作為其第一個參數。 您可以使用multiprocessing.cpu_count()
來獲取邏輯cpu核心的數量,然后在池中創建一半數量的進程(因此每個進程獲得2個)
multiprocessing.Pool(multiprocessing.cpu_count()/2)
這假設您的cpu計數除以2,對於幾乎所有的cpu來說都是真實的...
請注意,此解決方案不考慮SMT(或超線程),因為multiprocessing.cpu_count()
計數邏輯核心,因此它可能會報告物理核心增加一倍。 對於大多數CPU密集型任務,SMT可以提高性能,您可以執行兩倍的任務,但速度卻可以提高一半以上,如果您擁有SMT,則需要確定其是否對您的仿真有好處
最后,您還可以設置每個進程的相似性,使其只能在2個內核上運行,但是由於多重處理不會公開其打開的進程的PID,因此沒有直接的標准方法。 這是一些粗糙的完整代碼,可以為每個過程設置親和力:
import multiprocessing
import psutil
import itertools
cores_per_process = 2
cpu_count = multiprocessing.cpu_count()
manager = multiprocessing.Manager()
pid_list = manager.list() # trick to find pid of all the processes in the pool
cores_list = range(cpu_count)
it = [iter(cores_list)] * cores_per_process # this is a python trick to group items from the same list together into tuples
affinity_pool = manager.list(zip(*it)) # list of affinity
def Run_Case(params):
self_proc = psutil.Process() # get your own process
if self_proc.pid not in pid_list:
pid_list.append(self_proc.pid) # found new pid in pool
self_proc.cpu_affinity(affinity_pool.pop()) # set affinity from the affinity list but also remove it so other processes can't use the same affinity
#run simulation
a = range(1, len(U))
b = range(len(R))
paramlist = list(itertools.product(a, b))
pool = multiprocessing.Pool(cpu_count/cores_per_process) # decide on how many processes you want
pool.map(Run_Case, paramlist)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.