簡體   English   中英

並行案例的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM