Multiprocess and Multiprocessing with no file IO: OSError: [Errno 24] Too many open files

Multiprocess and Multiprocessing with no file IO: OSError: [Errno 24] Too many open files

总结:

我正在尝试使用 multiprocess 和 multiprocessing 来并行处理具有以下属性的工作:

错误:

我的方法适用于少量工作,但在执行较大任务时会失败:

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)}')

避免更改 ulimit 的方法是确保您的进程池大小不会增加到超过 1024。这就是为什么 1000 有效而 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

other threads recommend closing any opened files but I do not access files in my code

您没有打开文件,但您的进程正在打开文件描述符,这就是 OS 在这里看到的。

检查文件描述符的数量限制。我将 ulimit 从 1024 更改为 4096 并且它起作用了。 检查:

ulimit -n

对我来说是 1024,我将其更新为 4096 并且有效。

ulimit -n 4096