摘要
我试图使用多进程和多处理来并行化具有以下属性的工作:
基于当前系统datastructure
参数
误差
我的方法只适用于少量的工作,但在更大的任务上失败了:
OSError: [Errno 24] Too many open files
解决方案尝试
在macOS Catalina系统上运行,ulimit -n在Pycharm中给出1024。
有什么方法可以避免更改ulimit吗?我想避免这种情况,因为对于各种系统来说,代码最好是开箱即用的。
我在this thread这样的建议注释中使用.join和gc.collect的相关问题中看到过,其他线程建议关闭任何打开的文件,但我不访问代码中的文件。
import gc
import time
import numpy as np
from math import pi
from multiprocess import Process, Manager
from multiprocessing import Semaphore, cpu_count
def do_work(element, shared_array, sema):
shared_array.append(pi*element)
gc.collect()
sema.release()
# example_ar = np.arange(1, 1000) # works
example_ar = np.arange(1, 10000) # fails
# Parallel code
start = time.time()
# Instantiate a manager object and a share a datastructure
manager = Manager()
shared_ar = manager.list()
# Create semaphores linked to physical cores on a system (1/2 of reported cpu_count)
sema = Semaphore(cpu_count()//2)
job = []
# Loop over every element and start a job
for e in example_ar:
sema.acquire()
p = Process(target=do_work, args=(e, shared_ar, sema))
job.append(p)
p.start()
_ = [p.join() for p in job]
end_par = time.time()
# Serial code equivalent
single_ar = []
for e in example_ar:
single_ar.append(pi*e)
end_single = time.time()
print(f'Parallel work took {end_par-start} seconds, result={sum(list(shared_ar))}')
print(f'Serial work took {end_single-end_par} seconds, result={sum(single_ar)}')发布于 2021-04-07 15:41:53
避免更改ulimit的方法是确保进程池大小不会超过1024。这就是为什么1,000有效而10000失败的原因。
下面是一个使用池管理流程的示例,它将确保您不会超出您的ulimit值的上限:
from multiprocessing import Pool
def f(x):
return x*x
if __name__ == '__main__':
with Pool(5) as p:
print(p.map(f, [1, 2, 3]))https://docs.python.org/3/library/multiprocessing.html#introduction
其他线程建议关闭任何打开的文件,但我不访问代码中的文件
您没有打开文件,但是您的进程正在打开文件描述符,这正是操作系统在这里看到的。
发布于 2021-11-29 06:28:36
检查文件描述符数量的限制。我把我的上限从4096改成了1024,它起了作用。检查:
ulimit -n对我来说,它是1024,我把它更新为4096,它起了作用。
ulimit -n 4096https://stackoverflow.com/questions/66988750
复制相似问题