Pointers NASM ctypes SIMD-如何访问返回到ctypes的128位数组?

Pointers NASM ctypes SIMD-如何访问返回到ctypes的128位数组?,pointers,nasm,ctypes,Pointers,Nasm,Ctypes,我有一个由ctypes调用的NASM 64 dll。该程序将两个64位整数相乘并返回一个128位整数,因此我使用xmm SIMD指令。它循环10000次,并将结果存储在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]

我有一个由ctypes调用的NASM 64 dll。该程序将两个64位整数相乘并返回一个128位整数,因此我使用xmm SIMD指令。它循环10000次,并将结果存储在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位

有一篇文章是关于传入但不传出128位数组的

我的问题是:

-我应该使用movdqa或movdqu以外的指令吗?在众多SIMD指令中,这些似乎是最合适的


-Python可以处理任意大小的整数,但显然ctypes不能。当没有大于64位的ctypes时,有没有办法使用ctypes中的128位整数

您可以生成包含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'

谢谢,马克。您的示例适用于单个16字节的数字。我为50000个16字节的整数创建了一个800K字节的字符串缓冲区,但是在返回时,您的转换字符串只返回一个整数,即使我增加了切片索引。例如:return_array=int.from_bytesint128.raw[:160],“little”,signed=True只返回一个整数,而不是10个整数。如何将返回的数组转换为Python整数数组,而不仅仅是第一个值?我对.raw做了进一步的研究,但它并没有回答这个问题。@RTC222您必须一次遍历字符串16个字节来转换每个字节。例如.raw[0:16]然后.raw[16:32]等等,一行代码就可以这样做:arr=[int.from_bytesint128.raw[n:n+16],'little',对于0范围内的n,signed=True,lenit128.raw,16],这是有效的,但它引出了一个NASM特有的问题。我在50000个数据槽中任意插入了整数1983452,但它返回的是整数4701269677488209920。我认为这是因为64位数字是在偏移量0处插入的,但需要进行零扩展。因为它只填充16字节中的低位四字。我想我需要一个SIMD指令,所以我现在就调查一下。非常感谢您的帮助。我最后的评论不是答案-64位的值在较低的四字中。我还在寻找答案。
>>> hex(int.from_bytes(int128.raw[:16],'little',signed=True))
'0xaabbccddeeff'