【问题标题】:Python rpy2 and matplotlib conflict when using multiprocessing使用多处理时 Python rpy2 和 matplotlib 冲突
【发布时间】:2013-04-21 16:13:02
【问题描述】:

我正在尝试使用多处理来计算和生成图。在 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(我无法在任何 Mac 上安装 R 3.0 和 rpy2 最新版本而不会出现分段错误)。

错误是:

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

有什么想法吗?

【问题讨论】:

  • Rpy2-2.3.6 已于今天早些时候发布。它应该解决 OS X 上的段错误。
  • Laurent,非常感谢您提供新的 rpy2 版本。它现在可以与 R 3.0.0 完美配合。尽管如此,上面的错误保持不变:/

标签: python matplotlib multiprocessing rpy2


【解决方案1】:

我遇到了类似的问题,发现只要在 if name == main: 语句之后 将多处理中的 start 方法设置为使用 forkserver 就可以工作。

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()

【讨论】:

    【解决方案2】:

    尝试将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().
    

    他们都在使用第四代 i intel CPU(i5-4xxx with air 和 i7-4xxx with pro)。所以如果硬件上没有区别,那一定是软件上的。

    所以我刚刚尝试在 MacBook Pro 上将 matplot 更新到 3.0.3(当时是 3.0.1),一切正常。

    另外,再也不用pool.apply_async了。

    【讨论】:

    • 我认为这不能解决问题——我仍然在 matplotlib@3.1.1 上遇到错误。
    【解决方案3】:

    我的工作人员遇到了类似的问题,即加载一些数据、生成绘图并将其保存到文件中。请注意,这与 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
    

    【讨论】:

    • 这正是我的问题,所以感谢您发布,即使这不是 OP 的问题 :)。出于好奇 - 任何想法为什么更改后端可以解决问题?我的后端默认为macosx,因此问题似乎并非特定于TkAgg 后端(当我将其注释掉时,一切正常)。
    • 我看到了这个错误,即使我没有设置matplotlibrc 文件。大概这意味着我在macosx 后端,由于@bbruce 的回答所描述的原因,这是可以理解的错误。知道为什么你的可以工作,而我的不行吗?您是否默认使用与我在后台线程中工作的不同后端?
    【解决方案4】:

    当您在主线程之外执行 GUI 操作时,Mac OS X 上会发生此错误,这正是您通过将绘图功能转移到 multiprocessing.Pool 所做的事情(我想它在 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()
    

    希望这会有所帮助。

    【讨论】:

      【解决方案5】:

      这可能是 rpy2 特定的。 有报道称 OS X 和多处理 herethere 存在类似问题。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-12
        • 2016-04-30
        • 1970-01-01
        • 2016-12-19
        • 1970-01-01
        • 2012-07-20
        相关资源
        最近更新 更多