AES的NUMPY实现明显慢于纯python

AES的NUMPY实现明显慢于纯python,python,numpy,aes,Python,Numpy,Aes,我正在考虑重新实现SlowAES代码(),以尝试利用numpy的本机阵列支持。我得到了一个反直觉的结果,即SlowAES的纯Python比使用numpy实现的相同函数快得多。这是我有过的最清楚的例子 AES中的一个主要操作是移位行,其中4x4元素字节数组中的每一行移位一定数量的位置(0表示第0行,1表示第1行,等等)。原始Python代码将此4x4字节的状态数组视为一维16元素列表,然后使用切片创建要旋转的虚拟行: def rotate(word, n): return word[n:]

我正在考虑重新实现SlowAES代码(),以尝试利用numpy的本机阵列支持。我得到了一个反直觉的结果,即SlowAES的纯Python比使用numpy实现的相同函数快得多。这是我有过的最清楚的例子

AES中的一个主要操作是移位行,其中4x4元素字节数组中的每一行移位一定数量的位置(0表示第0行,1表示第1行,等等)。原始Python代码将此4x4字节的状态数组视为一维16元素列表,然后使用切片创建要旋转的虚拟行:

def rotate(word, n):
    return word[n:] + word [0:n]

def shiftRows(state):
    for i in range(4):
        state[i*4:i*4+4] = rotate(state[i*4:i*4+4], -i)
使用16个整数的列表在shiftRows上运行timeit会导致3.47微秒的时间

假设使用4x4整数输入数组,则在numpy中重新实现相同的函数将非常简单:

def shiftRows(state):
    for i in range(4):
        state[i] = np.roll(state[i],-i)
然而,时间它显示了16.3微秒的执行时间


我希望numpy优化的数组操作可能会产生更快的代码。我哪里做错了?有没有比纯Python更快实现AES的方法?我想得到一些中间结果,因此pycrypto可能不适用(尽管如果速度太慢,我可能不得不再看一看)


2016年9月7日-感谢您的回答。为了回答“为什么”这个问题,我正在研究运行几十万(如果不是几百万)个样本明文/密文对。因此,虽然任何单一加密的时差都不会产生什么影响,但从长远来看,我所能节省的任何时间都会产生巨大的影响。

简单的答案是,创建阵列会带来很大的开销。因此,在小列表上的操作通常比在数组上的等效操作要快。如果数组版本像列表版本一样是迭代的,则尤其如此。对于大型数组,使用编译方法的操作将更快

这4个“滚动”计时说明了这一点

对于小列表:

In [93]: timeit x=list(range(16)); x=x[8:]+x[:8]
100000 loops, best of 3: 2.75 µs per loop
In [94]: timeit y=np.arange(16); y=np.roll(y,8)
The slowest run took 40.90 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 14.5 µs per loop
对于大型的:

In [95]: timeit x=list(range(1000)); x=x[500:]+x[:500]
10000 loops, best of 3: 52.9 µs per loop
In [96]: timeit y=np.arange(1000); y=np.roll(y,500)
The slowest run took 28.91 times longer than the fastest. This could mean that an intermediate result is being cached.
10000 loops, best of 3: 22.2 µs per loop
我们可以通过从定时循环中提取
范围
arange
步骤来进一步细化问题

np.roll
操作基本上是:

y[np.concatenate((np.arange(8,16), np.arange(0,8)))]

它构造了4个数组,2个
arange
串联
,以及最终的索引数组。

“有没有比纯Python更快实现AES的方法?”几乎可以肯定。在C中执行此操作,并将绑定导出到Python。然而,我怀疑这不是你想要的答案。
Numpy
通常有更多的“控制”,如果与普通的“精简”源代码相比,它会减慢速度。检查
roll
的源代码:3.5 vs 16微秒?这个问题是否会扩大到你可能谈论的10秒或10分钟?我在这里没有看到什么大问题,除非这是一个为了优化而优化的问题。相关吗?我假设numpy版本中的
实际上应该是
状态