отключить все инструкции AVX-512 для сборки g ++

Привет, я пытаюсь построить без каких-либо инструкций avx512, используя эти флаги: -march=native -mno-avx512f. Однако я все еще получаю двоичный файл, в котором сгенерирована инструкция AVX512 (vmovss) (я использую elfx86exts для проверки). Есть идеи, как их отключить?


person sashas    schedule 27.08.2020    source источник
comment
Вы действительно хотите -march=native? Было бы проще использовать другой -march. В противном случае вы можете скомпилировать с -v и посмотреть на строку с cc1plus, чтобы увидеть, что вам нужно отключить. Кроме того, не могли бы вы объяснить, почему вы хотите избежать конкретных инструкций AVX512?   -  person Marc Glisse    schedule 27.08.2020
comment
@MarcGlisse Да, мне нужны все преимущества -march=native sans -mno-avx. Неужели я прошу так много? Другими словами, все -march=native должны корректно работать с -mno-avx или -mno-avx2.   -  person Maxim Egorushkin    schedule 28.08.2020
comment
vmovss является частью AVX (AVX1), а не только AVX512   -  person chtz    schedule 28.08.2020
comment
@MaximEgorushkin Это все еще не объясняет, почему. (sans означает без, поэтому ваше предложение звучит странно)   -  person Marc Glisse    schedule 28.08.2020
comment
@MarcGlisse: Я думаю, что Максим с точки зрения sans заключался в том, что -march=native -mno-avx заставит GCC прекратить испускать vmovss, и он не хотел так сильно искажать GCC, просто отключите AVX512, не отключая AVX1 / 2 / FMA. Но это противоречит второму предложению, так что да, IDK. Если это связано с частотой процессора, -mprefer-vector-width=256 в порядке: 256-битные векторы, использующие AVX512VL, обрабатываются так же, как векторы AVX1 / AVX2.   -  person Peter Cordes    schedule 28.08.2020
comment
Возможно, для оценки преимуществ AVX512 на текущей машине, например чтобы сравнить, на что будет похож полуискалеченный Pentium / Celeron? Есть шанс / надежда, что IceLake / TigerLake Pentium может иметь AVX2 (но не AVX512). Но с такой же вероятностью они и дальше будут полностью калечить их, как для Skylake Pentium, и поддерживать только SSE4.2, отключая все декодирование VEX и EVEX, включая отключение BMI1 / BMI2.   -  person Peter Cordes    schedule 28.08.2020


Ответы (2)


-march=native -mno-avx512f - правильный вариант, vmovss требуется только AVX1.

Существует кодировка AVX512F EVEX vmovss, но GAS не будет использовать ее, если задействованный регистр не равен xmm16..31. GCC не будет генерировать asm, используя эти регистры, когда вы отключите AVX512F с помощью -mno-avx512f или не активируете его в первую очередь с помощью чего-то вроде -march=skylake или -march=znver2.

Если вы все еще не уверены, проверьте фактический дизассемблер + машинный код, чтобы узнать, с какого префикса начинается инструкция:

  • C5 или C4 байт: начало 2- или 3-байтового префикса VEX, кодировка AVX1.
  • 62 байт: начало префикса EVEX, кодировка AVX512F

Пример:

.intel_syntax noprefix
vmovss xmm15, [rdi]
vmovss xmm15, [r11]
vmovss xmm16, [rdi]

собран с gcc -c avx.s и разобрать с objdump -drwC -Mintel avx.o:

0000000000000000 <.text>:
   0:   c5 7a 10 3f             vmovss xmm15,DWORD PTR [rdi]   # AVX1
   4:   c4 41 7a 10 3b          vmovss xmm15,DWORD PTR [r11]   # AVX1
   9:   62 e1 7e 08 10 07       vmovss xmm16,DWORD PTR [rdi]   # AVX512F

2- и 3-байтовые префиксы VEX и 4-байтовые префиксы EVEX перед кодом операции 10. (Байты ModRM тоже разные; xmm0 и xmm16 будут отличаться только дополнительным битом регистра от префикса, а не modrm).

GAS использует кодировку AVX1 VEX vmovss и другие инструкции, когда это возможно. Таким образом, вы можете рассчитывать на инструкции, которые имеют форму, отличную от AVX512F, по возможности использовать форму, отличную от AVX512F. Вот как набор инструментов GNU (используемый GCC) заставляет -mno-avx512f работать.

Это применимо , даже если кодировка EVEX короче. например когда [reg + constant] может использовать масштабированный disp8 AVX512 (масштабированный по ширине элемента), но для кодирования AVX1 потребуется 32-битное смещение, которое считается в байтах.

   f:   c5 7a 10 bf 00 01 00 00         vmovss xmm15,DWORD PTR [rdi+0x100]   # AVX1 [reg+disp32]
  17:   62 e1 7e 08 10 47 40    vmovss xmm16,DWORD PTR [rdi+0x100]           # AVX512 [reg + disp8*4]
  1e:   c5 78 28 bf 00 01 00 00         vmovaps xmm15,XMMWORD PTR [rdi+0x100]  # AVX1 [reg+disp32]
  26:   62 e1 7c 08 28 47 10    vmovaps xmm16,XMMWORD PTR [rdi+0x100]        # AVX512 [reg + disp8*16]

Обратите внимание на последний байт или последние 4 байта кодировок машинного кода: это 32-битное смещение 0x100 байтов с прямым порядком байтов для кодировок AVX1, но 8-битное смещение 0x40 dwords или 0x10 dqwords для кодировок AVX512.

Но используя переопределение asm-source {evex} vmovaps xmm0, [rdi+256], мы можем получить компактную кодировку даже для младших регистров:

62 f1 7c 08 28 47 10    vmovaps xmm0,XMMWORD PTR [rdi+0x100]

GCC, конечно, не будет делать этого с -mno-avx512f.

К сожалению, GCC и clang также пропускают эту оптимизацию при включении AVX512F, например при компиляции __m128 load(__m128 *p){ return p[16]; } с -O3 -march=skylake-avx512 (Godbolt). Используйте двоичный режим или просто обратите внимание на отсутствие тега {evex} в этой строке исходного кода asm вывода компилятора.

person Peter Cordes    schedule 28.08.2020

Я обнаружил ошибку в моем варианте использования. Один из скомпилированных модулей зависел от openvino SDK, который явно добавил флаг -mavx512f.

person sashas    schedule 30.08.2020