【发布时间】:2015-03-04 21:55:00
【问题描述】:
我正在使用 python 获取一个非常大的字符串(DNA 序列)并尝试从中创建一个后缀树。我的程序在制作嵌套对象很长时间后出现内存错误,所以我认为为了提高性能,从字符串创建缓冲区而不是实际切片字符串可能很有用。两个版本都在下面,并描述了它们的相关问题。
第一个(非缓冲)版本 - 在处理大字符串大约一分钟后,currNode.out[substring[0]] = self 发生 MemoryError。节点(pos, substring[1:])
class SuffixTree(object):
class Node(object):
def __init__(self, position, suffix):
self.position = position
self.suffix = suffix
self.out = {}
def __init__(self, text):
self.text = text
self.max_repeat = 2
self.repeats = {}
self.root = self.Node(None, '')
L = len(self.text)
for i in xrange(L):
substring = self.text[-1*(i+1):] + "$"
currNode = self.root
self.branch(currNode, substring, L-i-1, 0)
max_repeat = max(self.repeats.iterkeys(), key=len)
print "Max repeat is", len(max_repeat), ":", max_repeat, "at locations:", self.repeats[max_repeat]
def branch(self, currNode, substring, pos, repeat):
if currNode.suffix != '':
currNode.out[currNode.suffix[0]] = self.Node(currNode.position, currNode.suffix[1:])
currNode.suffix = ''
currNode.position = None
if substring[0] not in currNode.out:
currNode.out[substring[0]] = self.Node(pos, substring[1:])
if repeat >= self.max_repeat:
for node in currNode.out:
self.repeats.setdefault(self.text[pos:pos+repeat], []).append(currNode.out[node].position)
self.max_repeat = repeat
else:
newNode = currNode.out[substring[0]]
self.branch(newNode, substring[1:], pos, repeat+1)
**第二版 ** - 考虑到大字符串切片的不断保存可能是问题所在,我使用字符串缓冲区来实现所有切片。然而,这个版本几乎立即给出了一个 MemoryError for substring = buffer(self.text, i-1) + "$"
class SuffixTree(object):
class Node(object):
def __init__(self, position, suffix):
self.position = position
self.suffix = suffix
self.out = {}
def __init__(self, text):
self.text = text
self.max_repeat = 2
self.repeats = {}
self.root = self.Node(None, '')
L = len(self.text)
for i in xrange(L,0,-1):
substring = buffer(self.text, i-1) + "$"
#print substring
currNode = self.root
self.branch(currNode, substring, i-1, 0)
max_repeat = max(self.repeats.iterkeys(), key=len)
print "Max repeat is", len(max_repeat), ":", max_repeat, "at locations:", self.repeats[max_repeat]
#print self.repeats
def branch(self, currNode, substring, pos, repeat):
if currNode.suffix != '':
currNode.out[currNode.suffix[0]] = self.Node(currNode.position, buffer(currNode.suffix,1))
currNode.suffix = ''
currNode.position = None
if substring[0] not in currNode.out:
currNode.out[substring[0]] = self.Node(pos, buffer(substring,1))
if repeat >= self.max_repeat:
for node in currNode.out:
self.repeats.setdefault(buffer(self.text,pos,repeat), []).append(currNode.out[node].position)
self.max_repeat = repeat
else:
newNode = currNode.out[substring[0]]
self.branch(newNode, buffer(substring,1), pos, repeat+1)
我对缓冲区的理解在某种程度上是错误的吗?我认为使用它们可以帮助解决我的程序遇到的内存问题,而不是让它变得更糟。
【问题讨论】:
-
您使用什么样的序列文件,它们的大小是多少?还有你的 RAM 是什么样子的?
-
我正在输入 FASTA 文件,这些文件没有压缩或任何东西,我在 16gb 内存的笔记本电脑上运行。
-
FASTA 文件的大小是多少?或者如果有多个,有多少个,它们的平均大小是多少?
-
它像 FASTA 文件一样小,只有 4.5MB。我认为也许我编写程序的方式是问题所在。从本质上讲,它是在非常深的层次上使对象在对象内部的对象内部。我相信它可能在某个时候内存不足,无法再创建另一个新的“节点”对象并给出内存错误。我不确定如何正确调试内存问题,所以这只是假设。
标签: python string optimization buffer