Использование AVX для xor двух регистров zmm (512 бит)

Я хотел бы бит-wisr xor zmm0 с zmm1. Я читал в Интернете и пробовал:

asm volatile(
            "vmovdqa64 (%0),%%zmm0;\n"
            "vmovdqa64 (%1),%%zmm1;\n"
            "vpxorq %%zmm1, %%zmm0;\n"
            "vmovdqa64 %%zmm0,(%0);\n"

            :: "r"(p_dst), "r" (p_src)
             : );

Но компилятор выдает "Ошибка: несоответствие количества операндов для `vpxorq'".

Что я делаю не так?


person Epic    schedule 29.07.2019    source источник
comment
Встроенный asm для этого бесполезен (gcc.gnu.org/wiki/DontUseInlineAsm< /b>), и ваш код небезопасен и неэффективен, даже если вы исправили синтаксическую ошибку, добавив третий операнд. Используйте встроенный _mm512_xor_epi64( __m512i a, __m512i b);, как задокументировано в записи руководства Intel asm для pxor: felixcloutier.com/x86/pxor. Посмотрите на сгенерированный компилятором asm, если хотите увидеть, как это делается.   -  person Peter Cordes    schedule 29.07.2019
comment
Небезопасно, потому что у вас нет "memory" clobber, чтобы сообщить компилятору, что вы читаете/записываете память, и вы не объявляете clobbers на zmm0 или zmm1. И неэффективно по многим причинам, включая форсирование режимов адресации и неиспользование операнда-источника памяти. И не позволять компилятору выбирать, какие регистры использовать.   -  person Peter Cordes    schedule 29.07.2019


Ответы (2)


В большинстве инструкций AVX512 используется 3+ операнда, т.е. нужно добавить дополнительный операнд - регистр dst (он может совпадать с одним из других операндов).

Это также верно для версии AVX2, см. https://www.felixcloutier.com/x86/pxor:

VPXOR ymm1, ymm2, ymm3/m256

VPXORD zmm1 {k1}{z}, zmm2, zmm3/m512/m32bcst

Обратите внимание, что приведенный выше синтаксис Intel и примерно переводится как * mm1 = * mm2 ^ ** mm3, в вашем случае, я думаю, вы хотели использовать "vpxorq %%zmm1, %%zmm0, %%zmm0;\n"

Имейте в виду, что использование встроенного ассемблера, как правило, является плохой практикой, предназначенной для действительно особых случаев. SIMD-программирование лучше (быстрее, проще) выполняется с использованием встроенных функций, поддерживаемых всеми основными компиляторами. Вы можете просмотреть их здесь: https://software.intel.com/sites/landingpage/IntrinsicsGuide/

person Dan M.    schedule 29.07.2019
comment
OP использует синтаксис AT&T, где пунктом назначения является последний операнд, а не первый. Так что просто цитирование этой части руководства Intel не самое полезное. - person Peter Cordes; 29.07.2019
comment
@PeterCordes Я не согласен, так как нигде в своем ответе я не упомянул и не указал порядок операндов. Просто необходим дополнительный операнд. Я надеюсь, что человек, который пробует программировать на ассемблере, сможет сам понять, нужно ли это быть первым или последним. Я все же уточню. - person Dan M.; 29.07.2019
comment
Это все еще полезно, но я имел в виду, что это не так полезно, как могло бы быть. Вы процитировали синтаксис Intel VPXORD zmm1 {k1}{z}, zmm2, zmm3/m512/m32bcst, в котором, очевидно, пункт назначения указан первым, а источник последним. - person Peter Cordes; 29.07.2019
comment
Вы также не указали, что встроенный ассемблер все еще не работает, только теперь ошибка не является синтаксической ошибкой, а безопасностью: отсутствуют клоберы, как я прокомментировал вопрос. Думаю, я должен опубликовать это как ответ. - person Peter Cordes; 29.07.2019

Встроенный ассемблер для этого бесполезен (https://gcc.gnu.org/wiki/DontUseInlineAsm), и ваш код небезопасен и неэффективен, даже если вы исправили синтаксическую ошибку, добавив третий операнд.

Используйте встроенный _mm512_xor_epi64( __m512i a, __m512i b);, как описано в руководстве Intel asm для pxor. Посмотрите на сгенерированный компилятором asm, если хотите увидеть, как это делается.

Небезопасно, потому что у вас нет стирателя "memory", чтобы сообщить компилятору, что вы читаете/записываете память, и вы не объявляете стиратель на zmm0 или zmm1.

И неэффективно по многим причинам, включая форсирование режимов адресации и отсутствие использования операнда-источника памяти. И не позволять компилятору выбирать, какие регистры использовать.


Простое исправление синтаксиса asm, чтобы он компилировался, превратится из очевидной ошибки времени компиляции в незаметную и опасную ошибку времени выполнения, которая может быть видна только при включенной оптимизации.

Подробнее о встроенном asm см. https://stackoverflow.com/tags/inline-assembly/info. Но опять же, практически нет причин использовать его для большинства SIMD, потому что вы можете заставить компилятор сделать asm таким же эффективным, как то, что вы можете сделать вручную, и более эффективным, чем это.

person Peter Cordes    schedule 29.07.2019