簡體   English   中英

使用 joblib 和 SLURM 在 Python 中並行化 for 循環

[英]Parallelizing for-loops in Python using joblib & SLURM

我有一個包含 100 個元組tuplelist的列表,它們用作外部函數的輸入。 外部函數返回一個值,並將該值附加到一個數組中,就像這樣 ( MainFile.py ):

from ExternalPythonFile import ExternalFunction

valuelist = []
for a,b in tuplelist:
    value = ExternalFunction(a,b)
    # more functions here
    valuelist.append(value)
print(len(valuelist))

使用上面的 for 循環時print(len(valuelist))的輸出是(100,)

現在,由於元組的順序以及它們的附加方式在我的情況下並不重要,我想並行化 for 循環,因為處理 100 個元組需要大約 10 分鍾,並且我希望擴展該數字。 我在下面嘗試了一個 joblib 實現( MainFileJoblib.py ):

from ExternalPythonFile import ExternalFunction
from joblib import Parallel, delayed, parallel_backend
import multiprocessing

valuelist = []

def TupleFunction(a,b):
        value = ExternalFunction(a,b)
        # more functions here
        valuelist.append(value)

with parallel_backend('multiprocessing'):
    Parallel(n_jobs=10)(delayed(TupleFunction)(a,b) for a,b in tuplelist)

print(len(valuelist))

我在 unix 計算集群上運行所有這些,但運行時間仍然相似,大約 8 分鍾。 輸出也是錯誤的,它打印了(0,)

查看htop我發現實際上有 10 個內核被使用,但每個內核只有 20% 的使用率。

我還嘗試通過 SLURM 運行 joblib 實現:

srun --ntasks=1 --ncpus-per-task=10 python3 MainFileJoblib.py

這在大約 2 分鍾左右肯定更快,但它再次給出了錯誤的結果(0,)

並行化原始 for 循環的最佳方法是什么?

Joblib 自行管理輸出列表的創建和填充,因此可以輕松修復代碼:

from ExternalPythonFile import ExternalFunction
from joblib import Parallel, delayed, parallel_backend
import multiprocessing


with parallel_backend('multiprocessing'):
    valuelist = Parallel(n_jobs=10)(delayed(ExternalFunction)(a, b) for a, b in tuplelist)

print(len(valuelist))

如果由於某種原因你需要更新一個類似數組的對象,你可以使用 numpy memmap,按照下面的最小示例:

import tempfile
import numpy as np
from ExternalPythonFile import ExternalFunction
from joblib import Parallel, delayed, parallel_backend
import multiprocessing


# define function to update your array
def fill_array(mm_file, i, tuple_val):
    a, b = tuple_val
    value = ExternalFunction(a, b)
    # more functions here
    mm_file[i] = value

# create a temporary folder
tmp_dir = tempfile.mkdtemp()
# create a file where to dump your array
values_fname_memmap = Path(tmp_dir).joinpath("values_memmap")
values_memmap = np.memmap(values_fname_memmap.as_posix(),
                          dtype=np.float,
                          shape=(len(tuplelist), ),
                          mode='w+')

with parallel_backend('multiprocessing'):
    Parallel(n_jobs=10)(delayed(fill_array)(values_memmap, i, ab) 
                        for i, ab in enumerate(tuplelist))

print(len(values_memmap))

如果您需要對值應用一組轉換( # more functions ),只需圍繞 ExternalFunction 進行包裝,為給定的元組 (a, b) 輸出所需的值。

我希望盡管回復晚了,它仍然對你有用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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