Python:如何使用多个参数对函数进行多处理



我的函数sound_proc.windowing()从一个目录中分割一些声音文件,并将块保存到另一个目录。为了剪切目录中的所有文件,我在所有文件上使用for循环进行迭代:

# emodb_path_src = source folder with all sound files in it
# 512 = fix integer
# emodb_path_train = destination folder where all the cut files go
files = [l for l in listdir(emodb_path_src)]
for index, file in enumerate(files):
print(f'File: {index+1}/{len(files)}')
sound_proc.windowing(f'{emodb_path_src}{file}', 512, emodb_path_train)

不幸的是,这个过程非常缓慢,因为只使用了一个处理器核心。我已经用multiprocessingPool试过了,但我不能让它工作。如果有人能给我一些提示,让它在多个核心上运行,那就太好了。

提前感谢您,祝您今天愉快!

是的,您可以将多处理池与starmap结合使用。诀窍是创建一个可迭代的可迭代对象,包含所有函数调用的所有参数,如:

import multiprocessing as mp
# Precreate the args
args = [(f'{emodb_path_src}{file}', 512, emodb_path_train) for file in listdir(emodb_path_src)]
with mp.Pool(mp.cpu_count()) as pool:
print(pool.starmap(sound_proc.windowing, args))

根据问题的I/O绑定方式,您可能还想尝试ThreadPool。它使用起来更简单,在某些情况下甚至比Pool更快,因为它的设置开销更小。另一个额外的优点是它们共享相同的GIL,因此您可以访问相同的变量空间。下面是一个片段,请注意区别只是一个新的导入和with语句:

import multiprocessing as mp
from multiprocessing.pool import ThreadPool # thread-based Pool
# Precreate the args
args = [(f'{emodb_path_src}{file}', 512, emodb_path_train) for file in listdir(emodb_path_src)]
# If it's very I/O bound it might even be worthwhile creating more threads than CPU count!
with ThreadPool(mp.cpu_count()) as pool:
print(pool.starmap(sound_proc.windowing, args)) 

与此同时,我找到了一个很好的解决方案。冯·杰拉德的密码也很有魅力。我想简单地向你们展示一下我现在是如何解决这个问题的,以及用不同的方法可以节省多少时间。

原始帖子中的循环:

计算持续时间:~457.7秒

files = [l for l in listdir(emodb_path_src)]
for index, file in enumerate(files):
print(f'File: {index+1}/{len(files)}')
sound_proc.windowing(f'{emodb_path_src}{file}', 512, emodb_path_train)

Gerard提供的解决方案:

计算持续时间:~75.2秒

import multiprocessing as mp
args = [(f'{emodb_path_src}{file}', 512, emodb_path_train) for file in listdir(emodb_path_src)]

with mp.Pool(mp.cpu_count()) as pool:
pool.starmap(sound_proc.windowing, args)

使用joblib。并行:

计算持续时间:~68.8秒

from joblib import Parallel, delayed
import multiprocessing as mp
Parallel(n_jobs=mp.cpu_count(), backend='multiprocessing')(delayed(sound_proc.windowing)
(
sound_file=f'{emodb_path_src}{file}',
window_size=512,
dest=emodb_path_train
) for file in files)

最新更新