Конвертировать __m256d в __m256i - PullRequest
0 голосов
/ 24 июня 2018

Так как составлен так:

 __m256d a;

uint64_t t[4];

_mm256_store_si256( (__m256i*)t, (__m256i)a );/* Cast of 'a' to __m256i not allowed */

не допускается при компиляции в Visual Studio, я подумал, что мог бы использовать некоторые встроенные функции для преобразования значения __m256d в __m256i перед передачей его в _mm256_store_si256 и, таким образом, избежать приведения, который вызывает ошибку.

Но после просмотра этого списка я не смог найти функцию, принимающую в качестве аргумента значение __m256d и возвращающую значение __256i. Поэтому, возможно, вы могли бы помочь мне написать мою собственную функцию или найти нужную мне функцию, которая хранит 4x 64-битное двухбитное значение в массиве 4x64-битных целых чисел.

EDIT:

После дальнейших исследований я обнаружил _mm256_cvtpd_epi64 , который, кажется, именно то, что я хочу. Но мой процессор не поддерживает набор инструкций AVX512 ...

Что мне здесь делать?

1 Ответ

0 голосов
/ 24 июня 2018

Вы можете использовать _mm256_store_pd( (double*)t, a). Я почти уверен, что это безопасно для псевдонимов, потому что вы не разыменовываете указатель напрямую после его приведения. Свойство _mm256_store_pd оборачивает магазин всеми необходимыми псевдонимами.

(С AVX512 Intel перешла на использование void* для встроенных функций загрузки / хранения вместо float*, double* или __m512i*, чтобы устранить необходимость в этих неуклюжих приведениях и прояснить это. может псевдоним что угодно.)

Другой вариант - _mm256_castpd_si256, чтобы переосмыслить биты вашего __m256d как __m256i:

alignas(32) uint64_t t[4];
_mm256_store_si256( (__m256i*)t,  _mm256_castpd_si256(a));

Если вы читаете из t[] сразу, ваш компилятор может оптимизировать сохранение / перезагрузку и просто перемешать или pextrq rax, xmm0, 1 для извлечения битовых комбинаций FP непосредственно в целочисленные регистры. Вы можете написать это вручную с помощью встроенных функций. Однако сохранение / перезагрузка неплохо, особенно если вы хотите, чтобы в качестве скалярных целых чисел использовалось более 1 double битовых шаблонов.

Вы могли бы вместо этого использовать union m256_elements { uint64_t u64[4]; __m256d vecd; };, но нет гарантии, что скомпилируется эффективно.


Это приведение компилируется в ноль asm-инструкций, т.е. это просто каламбур, чтобы компилятор C был доволен .

Если вы действительно хотите округлить упакованное double до ближайшего 64-разрядного целого числа со знаком или без знака и получить результат в двоичном коде с дополнением или без знака 2 вместо двоичного кода IEEE754, вам необходим AVX512F _mm256/512_cvtpd_epi64 (* 1039) *) чтобы оно было эффективным. SSE2 + x86-64 может сделать это для скаляров, или вы можете использовать некоторые упакованные хаки FP для чисел в диапазоне [0..2^52]: Как эффективно выполнять преобразования double / int64 с SSE / AVX? .


Кстати, storeu не требует выровненного пункта назначения, но store. Если место назначения является локальным, вы должны выровнять его, а не использовать невыровненное хранилище, по крайней мере, если это происходит в цикле или эта функция может встроиться в более крупную функцию.

...