python - 为什么遍历枚举比生成器快得多?

标签 python optimization generator enumeration

最近,我在 Jon Clements 的帮助下发现了 this thread 以下代码的执行时间非常不同。

你知道为什么会这样吗?

评论:self.stream_data 是一个包含许多零和 int16 值的向量元组,create_ZS_data 方法正在执行所谓的 ZeroSuppression。

环境
输入:许多 (3.5k) 个小文件(每个约 120kb)
操作系统:Linux64
Python 版本 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 ] )

分析器信息:

   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>)

乔恩的解决方案:

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])


分析器信息:

   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)

最佳答案

我看了之前的讨论;您似乎对您的聪明理解在循环方面不如在源代码字符方面有效而感到困扰。当时我没有指出的是,这将是我更喜欢阅读的实现:

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 中追求疯狂的最小化。

关于python - 为什么遍历枚举比生成器快得多?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11611412/

相关文章:

python - 关于python中的def和return函数

python - Python 中的 importlib.reload() 和 exec()

python - 如何找出列表中以元音开头的单词?

algorithm - HackerRank 糖果分布

c - 检查字符数组是否为零的快速方法

node.js - node.js 中的花哨名称生成器

python - 如何将 fit_generator 与多个输入一起使用

python - 类生成器定义

python - 如何使用 tf.train.Scaffold 初始化评估的局部变量?

javascript - Gulp imagemin优化去除svg符号