最快的Python相当于切换整数数组

Joe*_*Joe 5 python optimization

我想找到switch用C语言完成工作的最快方法.我正在编写一些Python代码来替换C代码,除了瓶颈外,它们都运行良好.此代码用于紧密循环,因此获得最佳性能确实非常重要.

Optimsation尝试1: 第一次尝试,按照前文的问题,比如这个建议使用哈希表进行查找.这最终变得异常缓慢.

恐惧症尝试2 我所做的另一项优化是创建一系列if ... return语句,这使我的速度提升了13%.它仍然令人失望地缓慢.

Optimsation Attempt 3 我创建了array.array所有可能的输入值,并进行了索引查找.这导致总体加速度达到43%,这是可以接受的.

我正在运行一个array.array使用map并将转换函数传递给它.这个函数正在进行查找.我的开关正在处理短整数(它是一个类型化的数组).如果这是GCC C,编译器将创建一个跳转表.令人沮丧的是,要知道Python要么在查找​​表条目时要哈希值,要么在if的情况下进行大量的比较.我从分析中了解到,缓慢的功能正是正在进行查找的功能.

将一个整数映射到另一个整数的绝对最快方法是什么,映射在array.arrayif相关的位置.还有比上面更快的东西吗?

编辑

虽然它让我看起来只是一个白痴,只是为了实现,我会说它anwyay!请记住,在Profiler运行您的代码减慢你的代码下来不少.就我而言,慢了19倍.突然间,我的瓶颈并不是那么糟糕!非常感谢大家的所有答案.这个问题仍然有效.我会稍微提出这个问题,因为可能会有一些有趣的答案.

使用分析器,我的测试数据集:

real    0m37.309s
user    0m33.263s
sys     0m4.002s
Run Code Online (Sandbox Code Playgroud)

无:

real    0m2.595s
user    0m2.526s
sys     0m0.028s
Run Code Online (Sandbox Code Playgroud)

sen*_*rle 2

我认为其他人建议 numpy 或 pure c 是正确的;但对于纯Python,这里有一些时间安排,以了解它们的价值。基于这些,我有点惊讶它的array.array性能比dict. 您是否在循环内动态创建这些表?或者我是否误解了你的问题?无论如何,这表明 alist实际上是最好的选择。

>>> def make_lookup_func(table):
...     def lookup(val, t=table):
...         return t[val]
...     return lookup
... 
>>> lookup_tuple = make_lookup_func(tuple(range(10)))
>>> lookup_list = make_lookup_func(list(range(10)))
>>> lookup_array = make_lookup_func(array.array('i', range(10)))
>>> lookup_dict = make_lookup_func(dict(zip(range(10), range(10))))
>>> %timeit lookup_tuple(9)
10000000 loops, best of 3: 177 ns per loop
>>> %timeit lookup_list(9)
10000000 loops, best of 3: 158 ns per loop
>>> %timeit lookup_array(9)
10000000 loops, best of 3: 181 ns per loop
>>> %timeit lookup_dict(9)
10000000 loops, best of 3: 166 ns per loop
Run Code Online (Sandbox Code Playgroud)

缩放行为:

>>> lookup_tuple = make_lookup_func(tuple(range(10000)))
>>> lookup_list = make_lookup_func(list(range(10000)))
>>> lookup_array = make_lookup_func(array.array('i', range(10000)))
>>> lookup_dict = make_lookup_func(dict(zip(range(10000), range(10000))))
>>> %timeit lookup_tuple(9000)
10000000 loops, best of 3: 177 ns per loop
>>> %timeit lookup_list(9000)
10000000 loops, best of 3: 158 ns per loop
>>> %timeit lookup_array(9000)
10000000 loops, best of 3: 186 ns per loop
>>> %timeit lookup_dict(9000)
10000000 loops, best of 3: 195 ns per loop
Run Code Online (Sandbox Code Playgroud)