Код: Выделить всё
std::replace
Векторизованная реализация будет сравнивать и заменять несколько элементов одновременно.< br />Чтобы гарантировать сохранение старых значений там, где это необходимо, векторизованная реализация должна выполнить одно из следующих действий:
[*]Использовать векторные хранилища в маске
Записать старые значения для незамененных элементов
[*]Векторизировать только расположение элементов, по-прежнему заменяя каждый отдельным хранилищем
Первый подход выглядит лучше всего, но не работает, если в векторном наборе команд отсутствует замаскированное хранилище с заданным размером элемента. В x86 семейство SSE не имеет маскированных хранилищ1, AVX/AVX2 имеет только 32- и 64-битные маскированные хранилища элементов, и только если доступны некоторые подмножества AVX512, доступно каждое маскированное хранилище размера векторного элемента. .
Второй подход предполагает, что элемент можно записать, если записано одно и то же значение. Это предположение я подвергаю сомнению. Возможность записи в память не всегда предоставляется. В C++ можно передать постоянный массив с отброшенным
Код: Выделить всё
const
Код: Выделить всё
std::replace
Третий подход не требует маскированного хранилища и не предполагает возможности записи. Но векторизация также не дает полной пользы.
Я заметил, что в разных реализациях используются разные подходы. Оба
Код: Выделить всё
x86-64 icc 2021.10.0
Код: Выделить всё
x86-64 clang 17.0.1
Код: Выделить всё
std::replace
Код: Выделить всё
-mavx2
Код: Выделить всё
#include
void f(short* i, short* e)
{
std::replace(i, e, 0, 1);
}
Таким образом, это выглядит либо так, либо
Код: Выделить всё
x86-64 icc 2021.10.0
Код: Выделить всё
x86-64 clang 17.0.1
Помимо самой векторизации, для оптимизации могут использоваться избыточные записи.
Код: Выделить всё
std::replace
Код: Выделить всё
cmovcc
Поэтому мой вопрос: разрешено ли компиляторам и реализациям стандартных библиотек создавать избыточные хранилища для оптимизации
Код: Выделить всё
std::replace
Этот вопрос отличается от почти дублирующего Crash с icc: может ли компилятор изобрести записи там, где их не было в абстрактной машине? в том, что речь идет о стандартном алгоритме
Код: Выделить всё
std::replace
1 Non-temporal masked stores don't count, as they are not useful for general-purpose optimizations
Источник: https://stackoverflow.com/questions/780 ... ssed-array