最近,我在this主题的Jon Clements的帮助下发现以下代码的执行时间差异很大。
你知道为什么会这样吗?
注释: self.stream_data是一个带有许多零和int16值的向量元组,create_ZS_data方法正在执行所谓的ZeroSuppression。
环境
输入:许多(3.5k)小文件(每个约120kb)
操作系统: Linux64
Python ver 2.6.8
基于生成器的解决方案:
def create_ZS_data(self):
self.ZS_data = ( [column, row, self.stream_data[column + row * self.rows ]]
for row, column in itertools.product(xrange(self.rows), xrange(self.columns))
if self.stream_data[column + row * self.rows ] )
Profiler信息:
ncalls tottime percall cumtime percall filename:lineno(function)
3257 1.117 0.000 71.598 0.022 decode_from_merlin.py:302(create_ZS_file)
463419 67.705 0.000 67.705 0.000 decode_from_merlin.py:86(<genexpr>)
Jon的解决方案:
create_ZS_data(self):
self.ZS_data = list()
for rowno, cols in enumerate(self.stream_data[i:i+self.columns] for i in xrange(0, len(self.stream_data), self.columns)):
for colno, col in enumerate(cols):
# col == value, (rowno, colno) = index
if col:
self.ZS_data.append([colno, rowno, col])
Profiler信息:
ncalls tottime percall cumtime percall filename:lineno(function)
3257 18.616 0.006 19.919 0.006 decode_from_merlin.py:83(create_ZS_data)
答案 0 :(得分:4)
我看了之前的讨论;你似乎很困扰你的聪明理解在循环中不像源代码中的字符那样有效。我没有指出的是,这将是我首选的实现:
def sparse_table_elements(cells, columns, rows):
ncells = len(cells)
non_zeros = list()
for nrow in range(0, ncells, columns):
row = cells[nrow:nrow+columns]
for ncol, cell in enumerate(row):
if cell:
non_zeros.append([ncol, nrow, cell])
return non_zeros
我没有测试过,但我能理解它。由于潜在的效率低下,有几件事情在我身上迸发出来。重新计算两个恒定单调“无聊”指数的笛卡尔乘积必须是昂贵的:
itertools.product(xrange(self.rows), xrange(self.columns))
然后使用结果[(0, 0), (0, 1), ...]
从源代码中执行单个元素索引:
stream_data[column + row * self.rows]
这也比处理更大的切片更昂贵,因为“Jon”的实现确实如此。
发电机不是保证效率的秘诀。在这种特殊情况下,有135kb的数据已经被读入核心,一个构造不良的发电机似乎在耗费你的成本。如果您想要简洁的矩阵运算,请使用APL;如果你想要可读的代码,不要在Python中争取狂热的最小化。
答案 1 :(得分:2)
您可以轻松地将Jon的解决方案重写为生成器:
def create_ZS_data(self):
self.ZS_data = ([colno, rowno, col]
for rowno, cols in enumerate(self.stream_data[i:i+self.columns]
for i in xrange(0, len(self.stream_data), self.columns))
for colno, col in enumerate(cols)
if col)
我强烈期望这与Jon基于循环的解决方案的行为相同,这表明性能差异低至算法实现的中等规模细节。