【发布时间】:2014-07-11 20:02:51
【问题描述】:
背景
我在 NumPy 数组中有很多数字消息代码,我需要快速将它们转换为字符串。我在性能方面遇到了一些问题,想了解为什么以及如何让它变得更快。
一些基准
I - 微不足道的方法
import numpy as np
# dictionary to use as the lookup dictionary
lookupdict = {
1: "val1",
2: "val2",
27: "val3",
35: "val4",
59: "val5" }
# some test data
arr = np.random.choice(lookupdict.keys(), 1000000)
# create a list of words looked up
res = [ lookupdict[k] for k in arr ]
字典查找占用了我休息时间的大部分时间,758 毫秒。 (我也试过res = map(lookupdict.get, arr),但更糟。)
II - 没有 NumPy
import random
# dictionary to use as the lookup dictionary
lookupdict = {
1: "val1",
2: "val2",
27: "val3",
35: "val4",
59: "val5" }
# some test data
arr = [ random.choice(lookupdict.keys()) for _ in range(1000000) ]
# create a list of words looked up
res = [ lookupdict[k] for k in arr ]
计时结果变化很大,为 76 毫秒!
应该注意的是,我对定时查找感兴趣。随机生成只是为了创建一些测试数据。是否花费大量时间并不有趣。此处给出的所有基准测试结果仅适用于 100 万次查找。
III - 将 NumPy 数组转换为列表
我的第一个猜测是这与列表与数组问题有关。但是,通过修改 NumPy 版本以使用列表:
res = [ lookupdict[k] for k in list(arr) ]
给了我 778 毫秒,其中大约 110 毫秒用于转换列表,570 毫秒用于查找。所以,查找速度快了一点,但总时间是一样的。
IV - 从np.int32 到int 的类型转换
由于唯一的其他区别似乎是数据类型(np.int32 与 int),我尝试即时转换类型。这有点愚蠢,可能 dict 也是如此:
res = [ lookupdict[int(k)] for k in arr ]
但是,这似乎做了一些有趣的事情,因为时间下降到 266 毫秒。似乎几乎但不完全一样的数据类型在字典查找方面玩了讨厌的把戏,而且字典代码在转换方面效率不高。
V - 字典键转换为np.int32
为了测试这一点,我修改了 NumPy 版本以在 dict 键和查找中使用完全相同的数据类型:
import numpy as np
# dictionary to use as the lookup dictionary
lookupdict = {
np.int32(1): "val1",
np.int32(2): "val2",
np.int32(27): "val3",
np.int32(35): "val4",
np.int32(59): "val5" }
# some test data
arr = np.random.choice(lookupdict.keys(), 1000000)
# create a list of words looked up
res = [ lookupdict[k] for k in arr ]
这提高到 177 毫秒。这不是一个微不足道的改进,但与 76 毫秒相比相差甚远。
VI - 使用int对象的数组转换
import numpy as np
# dictionary to use as the lookup dictionary
lookupdict = {
1: "val1",
2: "val2",
27: "val3",
35: "val4",
59: "val5" }
# some test data
arr = np.array([ random.choice(lookupdict.keys()) for _ in range(1000000) ],
dtype='object')
# create a list of words looked up
res = [ lookupdict[k] for k in arr ]
这给出了 86 毫秒,这已经非常接近原生 Python 的 76 毫秒。
结果总结
- dict 键
int,使用int(本机Python)进行索引:76 毫秒 - dict 键
int,使用int对象 (NumPy) 进行索引:86 毫秒 - dict 键
np.int32,使用np.int32进行索引:177 毫秒 - dict 键
int,使用np.int32进行索引:758 毫秒
问题
为什么?我能做些什么来尽可能快地进行字典查找?我的输入数据是一个 NumPy 数组,所以到目前为止最好的(最快但丑陋的)是将 dict 键转换为np.int32。 (不幸的是,dict 键可能分布在很宽的数字范围内,因此逐个数组索引不是一个可行的选择。不过很快,10 毫秒。)
【问题讨论】:
标签: python python-2.7 numpy