我正在尝试在Mac OSX上使用Python(2.7.8)中的多处理。在阅读了Velimir Mlaker对这个问题的回答之后,我能够使用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
music21
的最新git命令具有基于约伯利布的多处理的某些棘手部分的功能。例如,如果要计算部分中的所有注释,则通常可以在序列上进行:
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)
但是!这是巨大的警告。让我们的时间这些:
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倍。为什么?因为准备多个流程的流都有很大的开销。如果正在运行的例程非常慢(大约1ms/Note除以处理器的数量),则值得在多处理中传递流。否则,查看是否只有一种方法可以来回传递一小部分信息,例如处理途径:
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上,我们也开始获得加速。在我的Office Mac Pro上,诸如此类的电话会得到巨大的速度。在这种情况下,对parse
的呼吁在整个时间内都大大统治了recurse()
。