Практическое использование автоматической векторизации?

StackOverflow https://stackoverflow.com/questions/409329

Вопрос

Кто-нибудь воспользовался преимуществами автоматической векторизации, которую может сделать gcc?В реальном мире (в отличие от примера кода)?Требуется ли реструктуризация существующего кода, чтобы воспользоваться преимуществами?Существует ли в каком-либо производственном коде значительное количество случаев, которые можно векторизовать таким образом?

Это было полезно?

Решение

Я еще не видел, чтобы GCC или Intel C++ автоматически векторизовали что-либо, кроме очень простых циклов, даже если у меня есть код алгоритмов, которые могут быть векторизованы (и были, после того как я вручную переписал их с использованием встроенных функций SSE).

Отчасти это связано с консервативностью - особенно когда он сталкивается с возможным псевдонимом указателя, компилятору C/C++ может быть очень сложно «доказать» самому себе, что векторизация будет безопасной, даже если вы, как программист, знаете, что это так.Большинство компиляторов (разумно) предпочитают не оптимизировать код, чтобы не рисковать его неправильной компиляцией.Это одна из областей, где языки более высокого уровня имеют реальное преимущество перед C, по крайней мере теоретически (я говорю теоретически, поскольку на самом деле мне не известны какие-либо автоматически векторизующие компиляторы ML или Haskell).

Другая часть этого — просто аналитические ограничения — насколько я понимаю, большая часть исследований в области векторизации связана с оптимизацией классических числовых задач (скажем, гидродинамики), которые были хлебом с маслом для большинства векторных машин несколько лет назад (когда между CUDA /OpenCL, Alivec/SSE и STI Cell, векторное программирование в различных формах стало широко доступно в коммерческих системах).

Маловероятно, что код, написанный для скалярного процессора, будет легко векторизовать компилятору.К счастью, многие вещи, которые вы можете сделать, чтобы компилятору было легче понять, как его векторизовать, например, мозаика цикла и частичное развертывание цикла, также (имеют тенденцию) повышать производительность на современных процессорах, даже если компилятор не понимает, как это сделать. векторизовать его.

Другие советы

Его сложно использовать в любой бизнес-логике, но он ускоряет обработку больших объемов данных таким же образом.

Хорошим примером является обработка звука/видео, при которой вы применяете одну и ту же операцию к каждому сэмплу/пикселю.Я использовал для этого VisualDSP, и вам нужно было после компиляции проверять результаты — действительно ли он используется там, где следует.

Векторизация будет в первую очередь полезна для числовых программ.Векторизованные программы могут работать быстрее на векторных процессорах, таких как процессор STI Cell, используемый в игровых консолях PS3.Там числовые вычисления, используемые, например, при рендеринге игровой графики, можно значительно ускорить за счет векторизации.Такие процессоры называются процессорами SIMD (Single Instruction Multiple Data).

На других процессорах векторизация использоваться не будет.Векторизованные программы выполняются с использованием векторизованного набора команд, который неприменим к процессору, не поддерживающему SIMD.

Серия процессоров Intel Nehalem (выпущенная в конце 2008 г.) реализует инструкции SSE 4.2, которые являются инструкциями SIMD.Источник: Википедия.

Векторизованные инструкции не ограничиваются процессорами Cell - они есть на большинстве современных ЦП, подобных рабочим станциям (PPC, x86, начиная с Pentium 3, Sparc и т. д.).При правильном использовании для операций с плавающей запятой он может очень помочь в решении очень интенсивных вычислительных задач (фильтры и т. д.).По моему опыту, автоматическая векторизация работает не так хорошо.

Возможно, вы заметили, что практически никто не знает, как эффективно использовать автоматическую векторизацию GCC.Если вы ищете в Интернете комментарии людей, вы всегда приходите к мысли, что GCC позволяет вам включить автоматическую векторизацию, но он крайне редко использует ее на практике, и поэтому, если вы хотите использовать ускорение SIMD (например:MMX, SSE, AVX, NEON, AltiVec), то вам, по сути, придется понять, как его написать, используя встроенные функции компилятора или код языка ассемблера.

Но проблема с внутренними функциями заключается в том, что вам фактически необходимо понять сторону языка ассемблера, а затем также изучить метод Intrinsics для описания того, что вы хотите, что, вероятно, приведет к гораздо менее эффективному коду, чем если бы вы написали его на ассемблере ( например, в 10 раз), потому что у компилятора по-прежнему будут проблемы с эффективным использованием ваших внутренних инструкций!

Например, вы можете использовать SIMD Intrinsics, чтобы многие операции могли выполняться параллельно одновременно, но ваш компилятор, вероятно, сгенерирует ассемблерный код, который передает данные между регистрами SIMD и обычными регистрами ЦП и обратно, эффективно делая ваш SIMD-код выполняется с той же скоростью (или даже медленнее), что и обычный код!

Итак, в основном:

  • Если вы хотите до 100% ускорения (2X скорость), то либо купите официальные компиляторы Intel/ARM, либо преобразуйте часть вашего кода, чтобы использовать внутреннюю внутреннюю часть SIMD C/C ++.
  • Если вы хотите ускорить 1000% (скорость 10x), запишите его в коде сборки, используя инструкции SIMD вручную.Или, если оно доступно на вашем оборудовании, вместо этого используйте ускорение графического процессора, например OpenCL или Nvidia CUDA SDK, поскольку они могут обеспечить такое же ускорение графического процессора, как SIMD в процессоре.
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top