python中的多进程任务无法被pickle?

时间:2015-05-08 22:41:44

标签: python stream python-multiprocessing music21

我试图在Mac OSX上使用python(2.7.8)中的多处理。在阅读了Velimir Mlaker对这个question的回答后,我能够使用multiprocessing.Pool()来处理一个简单的简单函数,但它并不适用于我的实际函数。我得到了正确的结果,但它是连续执行的。我相信问题是我的函数循环遍历music21.stream(),它类似于列表但具有音乐数据的特殊功能。我相信music21流不能被腌制,所以我可以使用一些多处理替代池吗?如果结果无序返回,我不介意,如果有必要,我可以升级到不同版本的python。我已经包含了我的多处理任务代码,但没有包含它调用的stream_indexer()函数。谢谢!

import multiprocessing as mp
def basik(test_piece, part_numbers):
    jobs = []
    for i in part_numbers:
        # Each 2-tuple in jobs has an index <i> and a music21 stream that
        # corresponds to an individual part in a musical score.
        jobs.append((i, test_piece.parts[i]))
    pool = mp.Pool(processes=4)
    results = pool.map(stream_indexer, jobs)
    pool.close()
    pool.join()

    return results

1 个答案:

答案 0 :(得分:1)

music21的最新git提交具有帮助处理基于joblib的多处理的一些棘手部分的功能。例如,如果要计算部件中的所有音符,通常可以按顺序进行:

import music21
def countNotes(s):
    return len(s.recurse().notes)
    # using recurse() instead of .flat to avoid certain caches...

bach = music21.corpus.parse('bach/bwv66.6')
[countNotes(p) for p in bach.parts]

同时它的工作原理如下:

music21.common.runParallel(list(bach.parts), countNotes)

BUT!这是一个巨大的警告。我们来看看时间:

In [5]: %timeit music21.common.runParallel(list(b.parts), countNotes)
10 loops, best of 3: 152 ms per loop

In [6]: %timeit [countNotes(p) for p in b.parts]
100 loops, best of 3: 2.19 ms per loop

在我的计算机(2核,4线程)上,并行运行比串行运行几乎100倍SLOWER。为什么?因为准备Stream进行多处理会产生很大的开销。如果正在运行的例程非常慢(大约1毫秒/笔记除以处理器数量),那么在多处理过程中值得传递Streams。否则,看看是否有办法只来回传递一小部分信息,例如处理路径:

def parseCountNotes(fn):
    s = corpus.parse(fn)
    return len(s.recurse().notes)  

bach40 = [b.sourcePath for b in music21.corpus.search('bwv')[0:40]]

In [32]: %timeit [parseCountNotes(b) for b in bach40]
1 loops, best of 3: 2.39 s per loop

In [33]: %timeit music21.common.runParallel(bach40, parseCountNotes)
1 loops, best of 3: 1.83 s per loop

即使在MacBook Air上,我们也开始获得加速。在我的办公室Mac Pro上,这样的通话速度非常快。在这种情况下,对parse的调用在recurse()的时间内占据主导地位。