Cython中的AES-NI内在函数?
Posted
技术标签:
【中文标题】Cython中的AES-NI内在函数?【英文标题】:AES-NI intrinsics in Cython? 【发布时间】:2016-11-12 17:52:46 【问题描述】:有没有办法在 Cython 代码中使用 AES-NI 指令?
我能找到的最接近的是有人如何访问 SIMD 指令: https://groups.google.com/forum/#!msg/cython-users/nTnyI7A6sMc/a6_GnOOsLuQJ
Python 线程中的 AES-NI 未得到回答: Python support for AES-NI
【问题讨论】:
类似pycrypto AESNI.c ? @J.J.Hakala 然后提供示例代码并将其作为答案。 【参考方案1】:您应该能够将内在函数定义为就好像它们是 Cython 中的普通 C 函数一样。类似的东西
cdef extern from "emmintrin.h": # I'm going off the microsoft documentation for where the headers are
# define the datatype as an opaque type
ctypedef struct __m128i:
pass
__m128i _mm_set_epi32 (int i3, int i2, int i1, int i0)
cdef extern from "wmmintrin.h":
__m128i _mm_aesdec_si128(__m128i v,__m128i rkey)
# then in some Cython function
def f():
cdef __m128i v = _mm_set_epi32(1,2,3,4)
cdef __m128i key = _mm_set_epi32(5,6,7,8)
cdef __m128i result = _mm_aesdec_si128(v,key)
问题“我如何在bytes
数组上应用它”?首先,你得到一个字节数组的char*
。然后用range
迭代它(注意不要跑到最后)。
# assuming you already have an __m128i key
cdef __m128i v
cdef char* array = python_bytes_array # auto conversion
cdef int i, j
# you NEED to ensure that the byte array has a length divisible by
# 16, otherwise you'll probably get a segmentation fault.
for i in range(0,len(python_bytes_array),16):
# go over in chunks of 16
v = _mm_set_epi8(array[i+15],array[i+14],array[i+13],
# etc... fill in the rest
array[i+1], array[i])
cdef __m128 result = _mm_aesdec_si128(v,key)
# write back to the same place?
for j in range(16):
array[i+j] = _mm_extract_epi8(result,j)
【讨论】:
这能否产生一个循环来解码数组,而无需在每次迭代中产生大量函数调用开销?如果没有,您可能需要编写编码/解码 C 函数。 是的 - 我相信是的。 Cython 可以生成可以迭代数组并调用 C 函数的 C 代码,其速度与 C 相当。(当 C 编译器看到这些“函数调用”时,它应该将它们直接转换为单个处理器指令(希望如此!)而不是实际做一个函数调用)。 执行_mm_extract_epi8
16 次看起来很可怕。如果幸运的话,它可能会编译为一个未对齐的存储,但如果不是,那将是一些令人讨厌的臃肿代码。
@PeterCordes 我同意!我敢肯定它可以做得更快。我真的只是想回答“如何在 Cython 中使用 AES-NI 指令?”的原始问题。我很高兴地承认,有效地使用这些说明(甚至知道它们实际上做了什么……)超出了我的知识范围。
@ThomasAhle 我想删除x
。我不知道为什么我最初把它放在那里,但我怀疑这是一个错误。它在没有x
的情况下为我编译(并且有意义)以上是关于Cython中的AES-NI内在函数?的主要内容,如果未能解决你的问题,请参考以下文章
带有 AVX SIMD 的 Cython:代码运行一次正确,但如果需要再次运行则挂起