Python 词典分配使Cython崩溃
下面的cython代码由于Python 词典分配使Cython崩溃,python,cython,Python,Cython,下面的cython代码由于word_idxs[token]=row语句而崩溃。如果我去掉那句话,一切都会好起来的。以下是我的观察结果 当以不同的文件作为参数时,代码工作正常 我尝试打印token,程序在不同时间因token的不同值而崩溃(导致错误的不是特定单词) 我尝试分配word_idxs[row]=row,但错误仍然存在。所以我认为这个错误与字符串无关 如果我一直分配给同一个键,则不会发生错误。例如:word_idxs['constant']=row 如果我删除cmatrix[row,col
word_idxs[token]=row
语句而崩溃。如果我去掉那句话,一切都会好起来的。以下是我的观察结果
token
,程序在不同时间因token
的不同值而崩溃(导致错误的不是特定单词)word_idxs[row]=row
,但错误仍然存在。所以我认为这个错误与字符串无关word_idxs['constant']=row
cmatrix[row,col]=fval
,那么一切都会正常工作 def cload(self, file_path, int dim, long vocab_size):
print("Loading")
cdef:
unsigned int row = 0
int col = 0
float [:,:] cmatrix
cdef dict word_idxs = {}
char* token
char* line
matrix = np.zeros([vocab_size, dim], dtype=np.dtype('f'))
cmatrix = matrix
with open(file_path, 'rb') as f:
for line in f:
token = strtok(line, ' \n')
print(row, token)
word_idxs[token] = row
for col in range(dim) :
val = strtok(NULL,' ')
fval = atof(val)
cmatrix[row, col] = fval
row += 1
对我来说,最明显的问题是,对
令牌
或val
的输出没有错误检查。如果strtok
到达字符串末尾,而您只是不处理这个问题,那么它可以是NULL
。由于缺乏可验证的例子,很难知道实际问题是什么
@ead在评论中指出了几个问题:
line
很可能是一个无效的指针(因为它所基于的Python对象从未保留过)cdef char* line_ptr
for line in f: # line IS NOT TYPED
line_ba = bytearray(line) # bytearray is mutable - changing it is fine
line_ptr = line_ba # line_ptr is valid as long as line_ba exists
您的代码和我建议的替换代码都在Python和C字符串之间进行了大量转换,这从来都不是非常快(而且很难做到正确)。这看起来是用Python编写的最简单的一种方法——我怀疑您是否真的从C调用中获益。我投了反对票,因为这不是一个最小的、完整的、可验证的示例。用你提供的代码复制你的bug是不可能的。我认为strtok的
line
改变了line
-它把\0
放在需要的地方。然而,这有可能改变不可变的Python字节。我想在大多数情况下不会发生这种情况,因为line
是一个悬空的指针-没有任何东西保存原始bytes对象的引用,因此它可能在此时已被破坏-因此崩溃(尽管不是100%确定)。然而,这对于内存中的字节对象来说是一个问题。使用python进行解析是一个非常好的建议。看看C是否有可能更快,这将是一件很有趣的事情。@ead关于更改行的说法是正确的。这是另一场即将发生的灾难,但确实使我的第二点无效。关于行
和悬垂的指针,你也是对的-我没有注意到。我怀疑C可以更快,但我非常不喜欢使用C字符串,所以不会是我让它更快:)