NASM ctypes SIMD - как получить доступ к 128-битному массиву, возвращенному в ctypes? - PullRequest
0 голосов
/ 25 мая 2018

У меня есть NASM 64 dll, вызываемая ctypes.Программа умножает два 64-разрядных целых числа и возвращает 128-разрядное целое число, поэтому я использую инструкции xmm SIMD.Он перебирает 10000 раз и сохраняет результаты в буфере памяти, созданном malloc.

Вот часть кода NASM, в которой выполняются вычисления SIMD:

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-битных целых чисел с помощью ctypes , который имеет дело с передачей, а не с выходом 128-битных массивов.

Мои вопросы:

- Должен ли я использовать инструкцию, отличную от movdqa или movdqu?Из многих инструкций SIMD они кажутся наиболее подходящими.

- Python может обрабатывать целые числа до любого произвольного размера, но, очевидно, ctypes не может.Есть ли способ использовать 128-битные целые числа из ctypes, если размер ctypes не превышает 64 бит?

1 Ответ

0 голосов
/ 25 мая 2018

Вы можете сгенерировать байтовые массивы, содержащие 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'
...