我之前对这个问题的想法:
必须使用适当的锁定机制来增强 scipy.weave.catalog 以序列化对目录的访问,或者每个实例都必须使用自己的目录。
我选择了后者。 scipy.weave.inline 函数使用一个目录,该目录绑定到scipy.weave.inline 模块的模块级名称function_catalog。这可以通过查看该模块的代码 (https://github.com/scipy/scipy/tree/v0.12.0/scipy/weave) 来发现。
现在最简单的解决方案是在程序开始时将此名称修改为其他名称:
from mpi4py import MPI
import numpy as np
import scipy.weave.inline_tools
import scipy.weave.catalog
import os
import os.path
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size()
catalog_dir = os.path.join(some_path, 'rank'+str(rank))
try:
os.makedirs(catalog_dir)
except OSError:
pass
#monkeypatching the catalog
scipy.weave.inline_tools.function_catalog = scipy.weave.catalog.catalog(catalog_dir)
现在inline 工作顺利:每个实例在公共 NFS 目录中都有自己的目录。当然,如果两个不同的并行任务同时运行,这种命名方案就会中断,但如果目录位于 /tmp 中,情况也会如此。
编辑:正如上面评论中提到的,如果多个独立作业并行运行,此过程仍然存在问题。这可以通过在路径名中添加一个随机 uuid 来解决:
import uuid
u = None
if rank == 0:
u = str(uuid.uuid4())
u = comm.scatter([u]*size, root=0)
catalog_dir = os.path.join('/tmp/<username>/pythoncompiled', u+'-'+str(rank))
os.makedirs(catalog_dir)
#monkeypatching the catalog
scipy.weave.inline_tools.function_catalog = scipy.weave.catalog.catalog(catalog_dir)
当然最好在计算后删除这些文件:
shutil.rmtree(catalog_dir)
编辑:还有一些其他问题。存放cpp和o文件的中间目录,由于不同实例同时访问,也遇到了一些麻烦,所以只好将上面的方法扩展到这个目录:
basetmp = some_path
catalog_dir = os.path.join(basetmp, 'pythoncompiled', u+'-'+str(rank))
intermediate_dir = os.path.join(basetmp, 'pythonintermediate', u+'-'+str(rank))
os.makedirs(catalog_dir, mode=0o700)
os.makedirs(intermediate_dir, mode=0o700)
#monkeypatching the catalog and intermediate_dir
scipy.weave.inline_tools.function_catalog = scipy.weave.catalog.catalog(catalog_dir)
scipy.weave.catalog.intermediate_dir = lambda: intermediate_dir
#... calculations here ...
shutil.rmtree(catalog_dir)
shutil.rmtree(intermediate_dir)