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 5

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) - это обоюдоострый меч, который может повредить вам, если вы не знаете, что делаете.