使用多处理时,Python rpy2和matplotlib冲突



我正在尝试使用多处理计算和生成地块。在Linux上,下面的代码可以正常运行,但是在Mac (ML)上它不能,给出下面的错误:

import multiprocessing
import matplotlib.pyplot as plt
import numpy as np
import rpy2.robjects as robjects
def main():
    pool = multiprocessing.Pool()
    num_figs = 2
    # generate some random numbers
    input = zip(np.random.randint(10,1000,num_figs), 
                range(num_figs))
    pool.map(plot, input)
def plot(args):
    num, i = args
    fig = plt.figure()
    data = np.random.randn(num).cumsum()
    plt.plot(data)
main()

Rpy2是Rpy2 ==2.3.1和R是2.13.2(我无法安装R 3.0和Rpy2最新版本在任何mac上没有得到分段错误)。

错误是:

The process has forked and you cannot use this CoreFoundation functionality safely. You MUST exec().
Break on __THE_PROCESS_HAS_FORKED_AND_YOU_CANNOT_USE_THIS_COREFOUNDATION_FUNCTIONALITY___YOU_MUST_EXEC__() to debug.
The process has forked and you cannot use this CoreFoundation functionality safely. You MUST exec().

我已经尝试了所有的方法来了解问题是什么,但是没有运气。我的配置是:

Danials-MacBook-Pro:~ danialt$ brew --config
HOMEBREW_VERSION: 0.9.4
ORIGIN: https://github.com/mxcl/homebrew
HEAD: 705b5e133d8334cae66710fac1c14ed8f8713d6b
HOMEBREW_PREFIX: /usr/local
HOMEBREW_CELLAR: /usr/local/Cellar
CPU: dual-core 64-bit penryn
OS X: 10.8.3-x86_64
Xcode: 4.6.2
CLT: 4.6.0.0.1.1365549073
GCC-4.2: build 5666
LLVM-GCC: build 2336
Clang: 4.2 build 425
X11: 2.7.4 => /opt/X11
System Ruby: 1.8.7-358
Perl: /usr/bin/perl
Python: /usr/local/bin/python => /usr/local/Cellar/python/2.7.4/Frameworks/Python.framework/Versions/2.7/bin/python2.7
Ruby: /usr/bin/ruby => /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby

任何想法?

当你在主线程之外执行GUI操作时,这个错误发生在Mac OS X上,这正是你通过将绘图函数转移到多进程所做的。池(我想它也不会在Windows上工作,因为Windows有相同的要求)。我能想象它工作的唯一方法是使用池来生成数据,然后让主线程在循环中等待返回的数据(队列是我通常处理它的方式…)。

这里有一个例子(认识到这可能不是你想要的-绘制所有的数字"同时"?- plt.show()块,所以一次只画一个,我注意到你没有它在你的样本代码-但没有我看不到任何东西在我的屏幕-然而,如果我把它拿出来-没有阻塞,没有错误,因为所有的GUI函数都发生在主线程):

import multiprocessing
import matplotlib.pyplot as plt
import numpy as np
import rpy2.robjects as robjects
data_queue = multiprocessing.Queue()

def main():
    pool = multiprocessing.Pool()
    num_figs = 10
    # generate some random numbers
    input = zip(np.random.randint(10,10000,num_figs), range(num_figs))  
    pool.map(worker, input)
    figs_complete = 0
    while figs_complete < num_figs:
        data = data_queue.get()
        plt.figure()
        plt.plot(data)
        plt.show()
        figs_complete += 1
def worker(args):
    num, i = args
    data = np.random.randn(num).cumsum()
    data_queue.put(data)
    print('done ',i)
main()

我的worker也有类似的问题,它正在加载一些数据,生成一个图,并将其保存到文件中。请注意,这与OP的情况略有不同,OP的情况似乎是围绕交互式绘图。尽管如此,我认为这是相关的。

我的代码的简化版本:

def worker(id):
    data = load_data(id)
    plot_data_to_file(data) # Generates a plot and saves it to a file.
def plot_something_parallel(ids):
    pool = multiprocessing.Pool()
    pool.map(worker, ids)
plot_something_parallel(ids=[1,2,3])

这会导致其他人提到的相同错误:

The process has forked and you cannot use this CoreFoundation functionality safely. You MUST exec().
Break on __THE_PROCESS_HAS_FORKED_AND_YOU_CANNOT_USE_THIS_COREFOUNDATION_FUNCTIONALITY___YOU_MUST_EXEC__() to debug.

按照@bbbruce的思路,我通过将matplotlib后端从TKAgg切换到默认值来解决问题。具体来说,我注释掉了matplotlibrc文件中的以下行:

#backend : TkAgg

这可能是rpy2特有的。在OS X和多进程中也有类似的问题。

我认为使用初始化器导入运行plot中代码所需的包可以解决这个问题(multiprocessing-doc)。

我有一个类似的问题,发现在多进程中设置启动方法使用forkserver工作,只要它出现在 if name == main:语句之后

if __name__ == '__main__':
    multiprocessing.set_start_method('forkserver')
    first_process = multiprocessing.Process(target = targetOne)
    second_process = multiprocessing.Process(target = targetTwo)
    first_process.start()
    second_process.start()

尝试将matplotlib升级到3.0.3:

pip3 install matplotlib --upgrade

那么一切都顺利了。

=======================================================================

不用再读了

昨天,我的多进程图在我的MacBook Air上工作。但是明天早上在我的MacBook Pro上不能使用相同的代码,显示许多:

The process has forked and you cannot use this CoreFoundation functionality safely. You MUST exec().
Break on __THE_PROCESS_HAS_FORKED_AND_YOU_CANNOT_USE_THIS_COREFOUNDATION_FUNCTIONALITY___YOU_MUST_EXEC__() to debug.
The process has forked and you cannot use this CoreFoundation functionality safely. You MUST exec().

他们都使用第4代英特尔CPU (i5-4xxx with air和i7-4xxx with pro)。因此,如果在硬件上没有区别,那么在软件上一定有区别。

所以我试着在MacBook Pro上更新matplot到3.0.3(原来是3.0.1),一切都很好。

也不需要再做pool.apply_async

最新更新