背景
我在NumPy数组中有很多数字消息代码,我需要快速将它们转换为字符串.我在性能方面遇到了一些问题,并希望了解为什么以及如何快速完成.
一些基准
我 – 琐碎的方法
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毫秒!
应该注意的是,我对查找计时感兴趣.随机生成只是为了创建一些测试数据.是否需要花费很多时间并不感兴趣.此处给出的所有基准测试结果仅适用于一百万次查找.
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毫秒.似乎几乎但不完全相同的数据类型在字典查找中发挥了令人讨厌的技巧,并且dict代码在转换时效率不高.
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 keys int,使用int(native python)索引:76 ms
> dict keys int,使用int对象建立索引(NumPy):86 ms
> dict keys np.int32,使用np.int32索引:177 ms
> dict keys int,使用np.int32索引:758 ms
问题(S)
为什么?我该怎么做才能尽快使字典查找?我的输入数据是一个NumPy数组,所以最好(最快但很难看)到目前为止将dict键转换为np.int32. (不幸的是,dict键可能分布在很多数字上,因此逐个数组索引不是一个可行的替代方案.但是快10分钟.)