我有一个由ctypes调用的NASM 64 dll。程序将两个64位整数相乘并返回一个128位整数,因此我使用的是xmm SIMD指令。它循环10,000次并将其结果存储在malloc创建的内存缓冲区中。
以下是执行SIMD计算的NASM代码部分:
cvtsi2sd xmm0,rax
mov rax,[pcalc_result_0]
cvtsi2sd xmm1,rax
PMULUDQ xmm0,xmm1
lea rdi,[rel s_ptr] ; Pointer
mov rbp,qword[rdi]
mov rcx,[s_ctr]
;movdqa [rbp + rcx],xmm0
movdqu [rbp + rcx],xmm0
add rcx,16
movdqa指令不起作用(程序崩溃,即使它是使用align = 16指令组装的)。 movdqu指令确实有效,但是当我将数组返回给ctypes时,我需要将返回指针转换为128位,但是没有128位的ctypes数据类型。这是ctypes代码的相关部分:
CallName.argtypes = [ctypes.POINTER(ctypes.c_double)]
CallName.restype = ctypes.POINTER(ctypes.c_int64)
n0 = ctypes.cast(a[0],ctypes.POINTER(ctypes.c_int64))
n0_size = int(a[0+1] / 8)
x0 = n0[:n0_size]
其中x0是返回的数组,转换为可用的形式,但不是128位。
Handling 128-bit integers with ctypes有一篇文章涉及传入128位数组但未传出。
我的问题是:
- 我应该使用movdqa或movdqu以外的指令吗?在许多SIMD指令中,这些指示似乎是最合适的。
- Python可以处理任意大小的整数,但显然ctypes不能。当没有大于64位的ctypes大小时,有没有办法使用来自ctypes的128位整数?
答案 0 :(得分:1)
您可以生成包含16个字节的字节数组,表示128位整数,并转换为字节格式。这可能不对齐,因此您应该使用movdqu
。我会使用输入/输出参数而不是返回值,因此Python可以管理内存:
>>> import ctypes
>>> value = 0xaabbccddeeff
>>> int128 = ctypes.create_string_buffer(value.to_bytes(16,'little',signed=True))
>>> int128
<ctypes.c_char_Array_17 object at 0x000001ECCB1D41C8>
>>> int128.raw
b'\xff\xee\xdd\xcc\xbb\xaa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
(注意:缓冲区以空值终止,这就是17字节的原因)
将此可写缓冲区传递给您的函数,该函数可以将结果写回同一缓冲区。返回时,使用以下命令转换回Python整数:
>>> hex(int.from_bytes(int128.raw[:16],'little',signed=True))
'0xaabbccddeeff'