Что такое "векторизация"?

Несколько раз я встречал этот термин в matlab, fortran ... какой-то другой... но я так и не нашел объяснения, что это значит и что он делает? Итак, я спрашиваю здесь, что такое векторизация и что означает, например, что "цикл векторизован"?

9 ответов

Решение

Многие ЦП имеют наборы команд "вектор" или "SIMD", которые применяют одну и ту же операцию одновременно к двум, четырем или более частям данных. Современные чипы x86 имеют инструкции SSE, многие чипы PPC имеют инструкции "Altivec", и даже некоторые чипы ARM имеют набор векторных инструкций, называемый NEON.

"Векторизация" (упрощенная) - это процесс переписывания цикла, так что вместо обработки одного элемента массива N раз он обрабатывает (скажем) 4 элемента массива одновременно N/4 раза.

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


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

for (int i=0; i<16; ++i)
    C[i] = A[i] + B[i];

Развертывание этого цикла превратит его в нечто вроде этого:

for (int i=0; i<16; i+=4) {
    C[i]   = A[i]   + B[i];
    C[i+1] = A[i+1] + B[i+1];
    C[i+2] = A[i+2] + B[i+2];
    C[i+3] = A[i+3] + B[i+3];
}

Векторизация, с другой стороны, производит что-то вроде этого:

for (int i=0; i<16; i+=4)
    addFourThingsAtOnceAndStoreResult(&C[i], &A[i], &B[i]);

Где "addFourThingsAtOnceAndStoreResult" является заполнителем для любых встроенных функций, используемых вашим компилятором для указания векторных инструкций. Обратите внимание, что некоторые компиляторы могут автоматически векторизовать очень простые циклы, подобные этому, которые часто можно включить с помощью параметра компиляции. Более сложные алгоритмы все еще требуют помощи программиста для создания хорошего векторного кода.

Векторизация - это термин для преобразования скалярной программы в векторную программу. Векторизованные программы могут выполнять несколько операций из одной инструкции, тогда как скалярные могут работать только с парами операндов одновременно.

Из википедии:

Скалярный подход:

for (i = 0; i < 1024; i++)
{
   C[i] = A[i]*B[i];
}

Векторизованный подход:

for (i = 0; i < 1024; i+=4)
{
   C[i:i+3] = A[i:i+3]*B[i:i+3];
}

Векторизация широко используется в научных вычислениях, где необходимо эффективно обрабатывать огромные порции данных.

В реальном программном приложении я знаю, что оно используется в NUMPY(не уверен в другом).

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

хотя существует множество объяснений, ЧТО ЗДЕСЬ ВЕКТОРИЗАЦИЯ ОПРЕДЕЛЕНА НА СТРАНИЦЕ NUMPY DOCUMENTATION

Векторизация описывает отсутствие какого-либо явного зацикливания, индексации и т. Д. В коде - все это происходит, конечно, просто "за кулисами" в оптимизированном, предварительно скомпилированном коде Си. Векторизованный код имеет много преимуществ, среди которых:

  1. векторизованный код более лаконичен и удобен для чтения

  2. меньше строк кода обычно означает меньше ошибок

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

  4. Векторизация приводит к большему количеству "Pythonic" кода. Без векторизации наш код был бы завален неэффективными и трудными для чтения циклами.

Простыми словами, векторизация означает оптимизацию алгоритма, чтобы он мог использовать SIMD-инструкции в процессорах.

AVX, AVX2 и AVX512 - это наборы команд (intel), которые выполняют одну и ту же операцию над несколькими данными в одной инструкции. например, AVX512 означает, что вы можете работать с 16 целочисленными значениями (4 байта) одновременно. Это означает, что если у вас есть вектор из 16 целых чисел, и вы хотите удвоить это значение в каждом целом числе, а затем добавить к нему 10. Вы можете либо загрузить значения в общий регистр [a,b,c] 16 раз и выполнить ту же операцию, либо выполнить ту же операцию, загрузив все 16 значений в SIMD-регистры [xmm,ymm] и выполнить операцию один раз. Это позволяет ускорить вычисление векторных данных.

В векторизации мы используем это в наших интересах, перемоделируя наши данные, чтобы мы могли выполнять SIMD-операции с ними и ускорять программу.

Единственная проблема с векторизацией - условия обработки. Потому что условия ветвят поток исполнения. Это может быть сделано путем маскировки. Путем моделирования условия в арифметическую операцию. например. если мы хотим добавить 10 к значению, если оно больше 100. мы можем либо.

if(x[i] > 100) x[i] += 10; // this will branch execution flow.

или мы можем смоделировать условие в арифметической операции, создав вектор условия c,

c[i] = x[i] > 100; // storing the condition on masking vector
x[i] = x[i] + (c[i] & 10) // using mask

хотя это очень тривиальный пример... таким образом, c - это наш маскирующий вектор, который мы используем для выполнения двоичной операции в зависимости от ее значения. Это позволяет избежать ветвления потока выполнения и обеспечивает векторизацию.

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

Я хотел бы остановиться на упоминании OpenMP, который позволяет векторизовать код с помощью прагм. Я считаю это хорошей отправной точкой. То же самое можно сказать и об OpenACC.

Это относится к способности выполнять одну математическую операцию над списком - или "вектором" - чисел за один шаг. Вы часто видите это с Фортраном, потому что это связано с научными вычислениями, которые связаны с суперкомпьютингом, где впервые появилась векторная арифметика. В настоящее время почти все настольные процессоры предлагают некоторую форму векторизованной арифметики посредством таких технологий, как Intel SSE. Графические процессоры также предлагают форму векторизованной арифметики.

Люди Intel, я думаю, легко понять.

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

Например, ЦП с 512-битным регистром может хранить 16 32-битных чисел двойной точности и выполнять одно вычисление.

В 16 раз быстрее, чем выполнение одной инструкции за раз. Сочетание этого с многопоточностью и многоядерностью процессоров дает прирост производительности на порядки.

Ссылка https://software.intel.com/en-us/articles/vectorization-a-key-tool-to-improve-performance-on-modern-cpus

В Java есть возможность включить это в JDK 15 2020 года или в конце JDK 16 в 2021 году.

https://bugs.openjdk.java.net/browse/JDK-8201271

Vector api - это первый JEP, предложенный для таргетинга в JDK 16.

https://bugs.openjdk.java.net/secure/Dashboard.jspa?selectPageId=19517

надеюсь, с тобой все хорошо!

Векторизация относится ко всем методам, которые преобразуют реализацию масштабатора, в которой одна операция обрабатывает один объект за раз, в векторную реализацию, в которой одна операция обрабатывает несколько объектов одновременно.

Векторизация относится к методу, с помощью которого мы оптимизируем код для эффективной работы с огромными блоками данных. применение векторизации можно увидеть в научных приложениях, таких как NumPy, pandas, также вы можете использовать эту технику при работе с Matlab, обработкой изображений, NLP и многим другим. В целом это оптимизирует время выполнения и распределение памяти программы.

Надеюсь, вы можете получить свой ответ!

Спасибо.

Я бы определил векторизацию как функцию данного языка, когда ответственность за итерацию элементов определенной коллекции может быть делегирована программистом (например, явным циклом элементов) какому-либо методу, предоставляемому языком (например, неявному циклу)..

Теперь, почему мы когда-либо хотим сделать это?

  1. Читаемость кода. В некоторых (но не во всех!) случаях работать со всей коллекцией сразу, а не с ее элементами, легче читать и быстрее кодировать;
  2. Некоторые интерпретируемые языки (R, Python, Matlab... но не Julia, например) очень медленно обрабатывают явные циклы. В этих случаях векторизация использует скомпилированные под капотом инструкции для этой «обработки порядка элементов» и может быть на несколько порядков быстрее, чем обработка каждой операции цикла, указанной программистом;
  3. Большинство современных процессоров (а в настоящее время и графических процессоров) имеют встроенное распараллеливание, которое можно использовать, когда мы используем метод векторизации, предоставляемый языком, а не наш собственный порядок операций элементов;
  4. Аналогичным образом выбранный нами язык программирования, скорее всего, будет использовать для некоторых операций векторизации (например, операций с матрицами) программные библиотеки (например, BLAS/LAPACK), которые используют возможности многопоточности ЦП, еще одну форму параллельных вычислений.

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

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

Смотрите два ответа выше. Я просто хотел добавить, что причина желания векторизации заключается в том, что эти операции могут легко выполняться в паралеле суперкомпьютерами и мультипроцессорами, что дает большой выигрыш в производительности. На однопроцессорных компьютерах не будет увеличения производительности.

Другие вопросы по тегам