14

我正在尝试使用多处理计算和生成图。在 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

有任何想法吗?

4

5 回答 5

12

当您在主线程之外执行 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()

希望这可以帮助。

于 2013-04-30T15:31:26.477 回答
10

我的工作人员遇到了类似的问题,正在加载一些数据,生成绘图并将其保存到文件中。请注意,这与 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
于 2014-05-27T16:22:27.983 回答
1

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

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

于 2013-04-28T07:28:54.497 回答
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()
于 2020-08-24T23:05:46.537 回答
-1

尝试将 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再做。

于 2019-03-13T06:45:04.157 回答