Я изучал эту проблему, подал отчет об ошибке GCC и обнаружил, что это проблема, связанная с MinGW64. См. ошибка GCC №49001. Судя по всему, GCC не поддерживает выравнивание стека по 32 байта в Windows. Это эффективно предотвращает использование 256-битных инструкций AVX.
Я исследовал несколько способов решения этой проблемы. Самое простое и прямолинейное решение — заменить выровненный доступ к памяти VMOVAPS/PD/DQA невыровненными альтернативами VMOVUPS и т. д. Итак, прошлой ночью я изучил Python (кстати, очень хороший инструмент) и выполнил следующий скрипт, который выполняет эту работу с входной ассемблерный файл, созданный GCC:
import re
import fileinput
import sys
# fix aligned stack access
# replace aligned vmov* by unaligned vmov* with 32-byte aligned operands
# see Intel's AVX programming guide, page 39
vmova = re.compile(r"\s*?vmov(\w+).*?((\(%r.*?%ymm)|(%ymm.*?\(%r))")
aligndict = {"aps" : "ups", "apd" : "upd", "dqa" : "dqu"};
for line in fileinput.FileInput(sys.argv[1:],inplace=1):
m = vmova.match(line)
if m and m.group(1) in aligndict:
s = m.group(1)
print line.replace("vmov"+s, "vmov"+aligndict[s]),
else:
print line,
Этот подход довольно безопасен и надежен. Хотя в редких случаях я наблюдал снижение производительности. Когда стек не выровнен, доступ к памяти пересекает границу строки кэша. К счастью, в большинстве случаев код работает так же быстро, как и выровненный доступ. Моя рекомендация: встроенные функции в критических циклах!
Я также попытался исправить распределение стека в прологе каждой функции, используя другой скрипт Python, стараясь всегда выравнивать его по 32-байтовой границе. Кажется, это работает для одного кода, но не для другого. Я должен полагаться на добрую волю GCC, что он будет выделять выровненные локальные переменные (относительно указателя стека), что он обычно и делает. Это не всегда так, особенно при серьезном сбросе регистров из-за необходимости сохранения всего регистра ymm перед вызовом функции. (Все регистры ymm сохраняют вызов). Скрипт могу выложить, если интересно.
Лучшим решением будет исправить сборку GCC MinGW64. К сожалению, я ничего не знаю о его внутренней работе, я только начал использовать его на прошлой неделе.
person
Norbert P.
schedule
17.05.2011
__attribute__ ((aligned (32)))
тоже не пользуется уважением? например если вы используете__m256 x __attribute__ ((aligned (32)))
- person nos   schedule 05.06.2014and $-32, %rsp
(или любое другое более высокое выравнивание) для выравнивания стека в функциях, которым необходимо передать__m256
,__m512
или любые объекты, которые вы объявили с помощьюalignas(32)
или чего-то большего, чем 16. Это кажется странной ошибкой, которую MinGW gcc не делает. Не используйте ту же последовательность, чтобы сохранить исходныйrsp
и выровнять его. - person Peter Cordes   schedule 07.11.2017