[英]Multiprocess tasks in python that can't be pickled?
我试图在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
最新的git commits music21
具有基于music21
功能,可帮助您处理多处理中一些棘手的部分。 例如,如果您要计算零件中的所有音符,通常可以连续进行:
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倍。 为什么? 因为准备要进行多处理的Stream会产生大量开销。 如果运行的例程非常慢(大约1ms / note除以处理器数量),则值得在多处理中传递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()
的时间内占据了主导地位。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.