У меня есть исходный файл C++, который скомпилирован с флагами -mavx/-mavx2
с помощью компилятора Clang.
Некоторые функции имеют реализации AVX2, но некоторые из них представляют собой просто стандартные вызовы.
Мне интересно, можно ли векторизовать std::sort
(1), std::memcpy
(2) и std::accumulate
из-за флага -mavx
? Поэтому удаление этого флага может повлиять на производительность этих функций. Спасибо.
Связанные: std::sort , std::fill_n и std::reduce все имеют многопоточные версии, которые делают то же, что std::sort
, std::memcpy
и std::accumulate
.
Да, все могут. Но детали различаются.
Функции memcpy
, memmove
и memset
реализованы как часть стандартной библиотеки C, это отдельно предварительно скомпилированная статическая или разделяемая библиотека. Реализация там уже должна быть векторизована. Однако компиляторы знают свою семантику и могут заменить вызовы стандартной библиотеки C встроенной реализацией, векторизованной, если векторизация применима.
Замена memcpy
на встроенную реализацию особенно полезна, когда размер известен заранее. В этом случае встроенная реализация наверняка превзойдет библиотечную, даже если библиотечная векторизована, поскольку знание размера является большим преимуществом.
Для очень маленьких известных размеров векторизировать нечего, это просто перемещение регистрами общего назначения. Для средних размеров алгоритм будет векторизован, а цикл будет полностью развернут. Наконец, для больших размеров компилятор может решить вызвать реализацию стандартной библиотеки C, поскольку встроенная реализация будет не намного лучше.
Алгоритмы типа std::accumulate
, reduce
или inner_product
являются шаблонными, поэтому у них нет предварительно скомпилированной реализации. Обычно с простыми типами данных и без подозрений в компиляторах с псевдонимами они автоматически векторизуются идеально.
Для более сложных алгоритмов у компилятора может не хватить возможностей для их автоматической векторизации. В этом случае реализация STL все равно может быть специализирована для их векторизации. Например, в STL недавно добавлена ручная векторизация, например, mismatch
в libc++ и MSVC STL. Обратите внимание, что подходы различаются для целей вашего вопроса: ручная векторизация libc++ встроена, а ручная векторизация MSVC компилируется отдельно.
std::sort
— один из самых сложных, но его все же можно векторизовать. Проверьте реализацию STL или выходные данные компилятора.
Флаг -mavx
/-mavx2
, скорее всего, повлияет на алгоритмы, которые автоматически векторизуются, но не компилируются отдельно, поэтому может повлиять или не повлиять на ваш случай.
Встроенная реализация (будь то автоматическая или ручная векторизация) обычно следует за флагами компиляции.
Отдельно скомпилированная реализация может быть скомпилирована с определенными флагами и иметь определенный уровень векторных инструкций или может использовать диспетчеризацию во время выполнения для нескольких уровней. Также гипотетически в зависимости от флагов могут быть выбраны разные отдельно скомпилированные реализации, но мне не известны такие примеры.
Компилятор знает исходный код или поведение этих функций, поэтому он может оптимизировать их по своему усмотрению (или так, как если бы вы написали их вручную). Обязательно скомпилируйте с помощью
-O3
(для gcc/clang) и проверьте, какой код создает компилятор.