3

我在这里可能有点过头了,但我正在用 python 做一个小的生物信息学项目。我正在尝试并行化一个分析大量字符串集的程序(RAM 中约 2-3GB)。我发现当我有较小的字典时,多处理版本更快,但几乎没有什么好处,而且对于大字典来说通常更慢。我的第一个理论是内存不足只会减慢一切,而瓶颈在于交换到虚拟内存。但是,我在具有 4*48GB RAM 的集群上运行该程序,并且发生了同样的减速。我的第二个理论是对某些数据的访问被锁定。如果一个线程试图访问当前正在另一个线程中访问的引用,该线程是否必须等待?我已经尝试创建我想要操作的字典的副本,但这似乎非常低效。还有什么可能导致我的问题?

我的多处理方法如下:

def worker(seqDict, oQueue):
     #do stuff with the given partial dictionary
     oQueue.put(seqDict)
oQueue = multiprocessing.Queue()
chunksize = int(math.ceil(len(sdict)/4)) # 4 cores
inDict = {}
i=0
dicts = list() 
for key in sdict.keys():
    i+=1
    if len(sdict[key]) > 0:
        inDict[key] = sdict[key]
    if i%chunksize==0 or i==len(sdict.keys()):
        print(str(len(inDict.keys())) + ", size")
        dicts.append(copy(inDict))
        inDict.clear()

for pdict in dicts:
    p =multiprocessing.Process(target = worker,args = (pdict, oQueue)) 
    p.start()
finalDict = {}

for i in range(4):
    finalDict.update(oQueue.get())
return finalDict
4

3 回答 3

2

正如我在评论中所说,正如 Kinch 在他的回答中所说,传递给子进程的所有内容都必须经过腌制和解除腌制才能在衍生过程的本地上下文中复制它。如果您使用multiprocess.Manager.dictfor sDict(从而允许进程通过代理在其上创建的对象的服务器共享相同的数据)并在该 shared 中生成带有切片索引的进程sDict,则应该减少生成中涉及的序列化/反序列化序列子进程。尽管在使用共享对象的服务器通信步骤中,您仍然可能会遇到瓶颈。如果是这样,您将不得不考虑简化数据,以便您可以使用真正的共享内存multiprocess.Arraymultiprocess.Value或查看multiprocess.sharedctypes创建自定义数据结构以在您的进程之间共享。

于 2012-07-25T15:25:08.660 回答
1

似乎“大型字符串集字典”中的数据可以重新格式化为可以存储在文件或字符串中的内容,从而允许您使用该mmap模块在所有进程之间共享它。如果每个进程需要将数据转换回其他更优选的形式,它可能会产生一些启动开销,但是可以通过向每个进程传递一些指示它们应该在共享内存中的整个数据集的哪个子集上进行工作的信息来最小化,并且只重构该过程所需的部分。

于 2012-07-25T15:39:30.017 回答
0

通过队列传递的每个数据都将使用 pickle 进行序列化和反序列化。如果您传递大量数据,我想这可能是一个瓶颈。

您可以减少数据量,利用共享内存,在 ac 扩展中编写多线程版本,或者尝试使用 python 的多线程安全实现(可能是 jython 或 pypy;我不知道)的多线程版本。

哦,顺便说一句:您使用的是多处理而不是多线程。

于 2012-07-25T15:02:20.143 回答