【发布时间】:2009-08-20 22:11:33
【问题描述】:
一个简单的问题,真的:您有十亿 (1e+9) 个无符号 32 位整数作为十进制 ASCII 字符串存储在 TSV(制表符分隔值)文件中。与处理同一数据集的其他工具相比,使用 int() 的转换速度非常慢。为什么?更重要的是:如何让它更快?
因此问题是:在 Python 中,将字符串转换为整数的最快方法是什么?
我真正想到的是一些半隐藏的 Python 功能,可以(ab)用于此目的,这与 Guido 在他的 "Optimization Anecdote" 中使用 array.array 不同。
示例数据(标签扩展为空格)
38262904 "pfv" 2002-11-15T00:37:20+00:00
12311231 "tnealzref" 2008-01-21T20:46:51+00:00
26783384 "hayb" 2004-02-14T20:43:45+00:00
812874 "qevzasdfvnp" 2005-01-11T00:29:46+00:00
22312733 "bdumtddyasb" 2009-01-17T20:41:04+00:00
读取数据的时间在这里无关紧要,处理数据是瓶颈。
微基准测试
以下所有语言都是解释性语言。主机运行 64 位 Linux。
Python 2.6.2 和 IPython 0.9.1,每秒约 214k 次转换 (100%):
In [1]: strings = map(str, range(int(1e7)))
In [2]: %timeit map(int, strings);
10 loops, best of 3: 4.68 s per loop
REBOL 3.0 版本 2.100.76.4.2,~231kcps (108%):
>> strings: array n: to-integer 1e7 repeat i n [poke strings i mold (i - 1)]
== "9999999"
>> delta-time [map str strings [to integer! str]]
== 0:00:04.328675
REBOL 2.7.6.4.2(2008 年 3 月 15 日),~523kcps(261%):
正如 John 在 cmets 中指出的那样,此版本不构建转换后的整数列表,因此给出的速度比相对于 Python 的 4.99 秒运行时 for str in strings: int(str)。
>> delta-time: func [c /local t] [t: now/time/precise do c now/time/precise - t]
>> strings: array n: to-integer 1e7 repeat i n [poke strings i mold (i - 1)]
== "9999999"
>> delta-time [foreach str strings [to integer! str]]
== 0:00:01.913193
KDB+ 2.6t 2009.04.15,~2016kcps (944%):
q)strings:string til "i"$1e7
q)\t "I"$strings
496
【问题讨论】:
-
尝试
numpy.fromfile加载“十亿正整数”(顺便说一句,“十亿”是什么意思(在美国是10**9,在英国可能是10**12)? -
十亿左右的好收获;尽管后一种用法在 1970 年代在英国已经过时。
-
你试过编译代码吗?
-
(1) 请比“在文本文件中存储为 ASCII 字符串”更明确。固定列还是分隔?这是文件中唯一的数据类型吗?显示一些示例行。 (2) 向我们展示您当前正在使用的代码,如果您希望我们相信 int() 是问题并且这不是家庭作业问题 (3) 请以 SI 单位表示速度,而不是“非常慢” ”。 (4) 还有哪些工具? (5)什么平台,什么版本的Python?
-
(6) 整数的平均位数是多少? (7) 数字是十进制/十六进制/八进制/其他吗?
标签: python performance optimization