gpt4 book ai didi

Python 多处理 + scipy : excessive filesystem 'stat' and 'open' attempts

转载 作者:太空宇宙 更新时间:2023-11-03 13:21:53 24 4
gpt4 key购买 nike

我正在观察 Python 中的一些极端奇怪的行为。考虑以下代码:

from multiprocessing import Process  
import scipy

def test():
pass

for i in range(1000):
p1 = Process(target=test)
p1.start()
p1.join()
print i

当我对此运行 strace -f 时,我从循环中得到以下片段:

clone(Process 19706 attached
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x2b23afde1970) = 19706
[pid 19706] set_robust_list(0x2b23afde1980, 0x18) = 0
[pid 18673] wait4(19706, Process 18673 suspended
<unfinished ...>
[pid 19706] stat("/apps/python/2.7.1/lib/python2.7/multiprocessing/random", 0x7fff041fc150) = -1 ENOENT (No such file or directory)
[pid 19706] open("/apps/python/2.7.1/lib/python2.7/multiprocessing/random.so", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid 19706] open("/apps/python/2.7.1/lib/python2.7/multiprocessing/randommodule.so", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid 19706] open("/apps/python/2.7.1/lib/python2.7/multiprocessing/random.py", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid 19706] open("/apps/python/2.7.1/lib/python2.7/multiprocessing/random.pyc", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid 19706] open("/dev/urandom", O_RDONLY) = 3
[pid 19706] read(3, "\3\204g\362\260\324:]\337F0n\n\377\317\343", 16) = 16
[pid 19706] close(3) = 0
[pid 19706] open("/dev/null", O_RDONLY) = 3
[pid 19706] fstat(3, {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 3), ...}) = 0
[pid 19706] exit_group(0) = ?
Process 18673 resumed
Process 19706 detached

关于在文件系统中搜索“随机”的那些垃圾是怎么回事?我真的想避免这种情况,因为我在集群上并行运行了很多具有这种结构的进程,并且循环速度非常快,而且这种文件系统事件正在阻塞文件系统元数据服务器,或者集群管理员告诉我.

如果我删除“import scipy”命令,那么这个问题就会消失:

clone(Process 23081 attached
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x2b42ec15e970) = 23081
[pid 23081] set_robust_list(0x2b42ec15e980, 0x18) = 0
[pid 22052] wait4(23081, Process 22052 suspended
<unfinished ...>
[pid 23081] open("/dev/null", O_RDONLY) = 3
[pid 23081] fstat(3, {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 3), ...}) = 0
[pid 23081] exit_group(0) = ?
Process 22052 resumed
Process 23081 detached

但我需要在我的真实代码中使用 scipy,所以我无法摆脱它。或者也许我可以,但那会很痛苦。

有谁知道我为什么会看到这种行为?如果它是某些版本的怪癖,我正在运行以下命令:

python :2.7.1,多处理:0.70a1,科学:0.9.0,

实际上,因为我刚刚意识到它可能是系统相关的,所以我在我的笔记本电脑上运行了相同的代码并且没有问题(即输出相当于第二种情况)。在我运行的笔记本电脑上

python :2.6.5,多处理:0.70a1,科学:0.10.0,

也许是早期版本scipy的问题或者bug已经修复了?我对此类内容的搜索一无所获。即使这是问题所在,在集群上更改 scipy 的版本也不是那么容易,尽管如果需要我可能会让集群管理员构建更新的版本。

这可能是问题所在吗?

最佳答案

这不是因为 Windows 或 __main__ 模块。这也不是 Python 喜欢做生意的方式。而且,如果您重新检查,我想您会发现这是 Python 2.6 的行为,而不是 2.7 的行为,除非您运行的是经过修改的 2.7。

您是完全正确的,问题源于 multiprocessing.forking 模块中的随机模块初始化步骤——它旨在防止您的进程在 fork 生成 n workers,从创建所有通过完全相同的伪随机数系列前进的 worker(例如,如果他们都使用这些数字协商 SSL 连接,这可能会危及安全性):

        if 'random' in sys.modules:
import random
random.seed()

但是这里的关键是要认识到上面的import语句应该从系统调用的角度来看是一个空操作,因为如果一个模块名已经作为键存在于 sys.modules 字典中,然后 import 简单地返回它在那里找到的值,而不试图从文件系统加载任何东西:

>>> import sys
>>> sys.modules['fake'] = 'Not even a module'
>>> import fake
>>> fake
'Not even a module'

因此,上面引用的 if 语句专门试图防止 >random 模块甚至还没有被加载。当你在没有加载 scipy 的情况下进行实验时,if 语句体甚至都不会触发。

那么问题是什么?

问题是 Python 2.7 之前的旧版本让你通过在包内的模块中说 import foo 来表示两个不同的东西:你可能是尝试相对导入 the_package.foo,或者您可能正在尝试导入顶级包 foo。请参阅 PEP 328 以详细了解为什么在更新的 Python 版本中更改了这种模棱两可且代价高昂的行为:

http://legacy.python.org/dev/peps/pep-0328/

有了这个背景,您可以查看您的 strace 输出,并注意到这里的答案中还没有人提到的东西:stat()open () 列出的系统调用不是试图导入模块 random 而是名为 multiprocessing.random 的不存在的模块!

这是尝试附加导入的关键原因,即使 random 已经在 sys.modules 中列出——因为在 Python 之前2.6 允许退回到 import 语句真正旨在导入 random 的假设,它必须消除它试图相对导入 的可能性code>multiprocessing.random 因为 import 语句出现在 multiprocessing.forking 子模块的代码中。

程序员真的应该说 sys.modules['random'].seed() 而不是尝试重新导入来避免那些额外的系统调用。但希望一旦您有机会升级到更新版本的 Python,您就不会被这种行为困扰太久。

关于Python 多处理 + scipy : excessive filesystem 'stat' and 'open' attempts,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10973869/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com