Visual Studio 2017: mm load ps часто компилируется в movups
Я смотрю на сгенерированную сборку для моего кода (используя Visual Studio 2017) и заметил, что _mm_load_ps часто (всегда?) компилируется в movups.
Данные, которые я использую _mm_load_ps, определяются следующим образом:
struct alignas(16) Vector {
float v[4];
}
// often embedded in other structs like this
struct AABB {
Vector min;
Vector max;
bool intersection(/* parameters */) const;
}
Теперь, когда я использую эту конструкцию, произойдет следующее:
// this code
__mm128 bb_min = _mm_load_ps(min.v);
// generates this
movups xmm4, XMMWORD PTR [r8]
Я ожидаю movaps из-за alignas(16). Нужно ли что-то еще, чтобы убедить компилятор использовать movaps в этом случае?
EDIT: мой вопрос отличается от этот вопрос потому что я не получаю никаких сбоев. Структура специально выровнена,и я также использую выровненное распределение. Скорее, мне любопытно, почему компилятор переключает _mm_load_ps (встроенный для выровненной памяти) на movups. Если я знаю, что struct был выделен по выровненному адресу, и я вызываю его через это* было бы безопасно использовать movaps, не так ли?
1 ответ:
О последних версиях Visual Studio и компилятора Intel (последние версии после 2013 года?), компилятор редко когда-либо генерирует выровненные SIMD load / stores больше.
При компиляции для AVX или выше:
- компилятор Microsoft (>VS2013?) не генерирует выровненные нагрузки. Но он по-прежнему генерирует выровненные магазины.
- компилятор Intel (>Parallel Studio 2012?) больше так не делает. Но вы все равно увидите их в ICC-скомпилированных двоичных файлах внутри их оптимизированные вручную библиотеки, такие как
memset()
.- начиная с GCC 6.1, он по-прежнему генерирует выровненную нагрузку/хранилища при использовании выровненных встроенных компонентов.
Компилятору разрешено делать это, потому что это не потеря функциональности, когда код написан правильно. Все процессоры, начиная с Nehalem, не имеют штрафа за несогласованную загрузку / хранение, Когда адрес выровнен.
Позиция Microsoft по этому вопросу заключается в том, что она "помогает программисту, не давая сбоев". К сожалению, я не могу найти исходного источника для этого заявления от Microsoft больше нет. На мой взгляд, это достигается прямо противоположным образом, поскольку скрывает штрафы за несоосность. С точки зрения корректности, он также скрывает неверный код.Как бы то ни было, безусловно, использование несогласованных load/stores немного упрощает компилятор.
Новые Релевантности:
- начиная с Parallel Studio 2018, компилятор Intel больше не генерирует выровненные движения вообще - даже для предварительно Нихалем цели.
- начиная с Visual Studio 2017, компилятор Microsoft также больше не генерирует выровненные движения вообще - даже при ориентации на оборудование до AVX.
Оба случая приводят к неизбежному снижению производительности на старых процессорах. Но, похоже, что это сделано намеренно, поскольку и Intel, и Microsoft больше не заботятся о старых процессорах.
Единственная внутренняя нагрузка/хранилище, которая невосприимчива к этому,-это вневременная нагрузка/хранилища. Есть у них нет невыровненного эквивалента, поэтому у компилятора нет выбора.
Поэтому, если вы хотите просто проверить корректность вашего кода,Вы можете заменить в load/store встроенные функции на вневременные. Но будьте осторожны, чтобы не позволить чему-то подобному проскользнуть в производственный код, поскольку NT load/stores (в частности, NT-stores) - это обоюдоострый меч, который может повредить вам, если вы не знаете, что делаете.