现在,我已经在matlab, fortran中遇到过几次这个术语…其他的…但我从来没有找到一个解释,它是什么意思,它是什么?所以我在这里问,什么是向量化,例如,“一个循环是向量化的”是什么意思?
当前回答
我会将向量化定义为给定语言的一个特性,其中如何遍历某个集合的元素的责任可以从程序员委托给语言提供的一些方法(例如,显式的元素循环)。
我们为什么要这么做呢?
Code readeability. For some (but not all!) cases operating over the entire collection at once rather than to its elements is easier to read and quicker to code; Some interpreted languages (R, Python, Matlab.. but not Julia for example) are really slow in processing explicit loops. In these cases vectorisation uses under the hood compiled instructions for these "element order processing" and can be several orders of magnitude faster than processing each programmer-specified loop operation; Most modern CPUs (and, nowadays, GPUs) have build-in parallelization that is exploitable when we use the vectorisation method provided by the language rather than our self-implemented order of operations of the elements; In a similar way our programming language of choice will likely use for some vectorisation operations (e.g. matrix operations) software libraries (e.g. BLAS/LAPACK) that exploit multi-threading capabilities of the CPU, another form of parallel computation.
请注意,对于第3点和第4点,一些语言(特别是Julia)允许这些硬件并行也使用程序员定义的顺序处理(例如for循环),但这是自动发生的,在使用语言提供的向量化方法时。
现在,虽然向量化有许多优点,但有时算法使用显式循环比向量化更直观地表达(可能我们需要求助于复杂的线性代数运算、单位和对角矩阵……所有这些都是为了保留我们的“向量化”方法),如果使用显式排序形式没有计算上的缺点,那么这个应该是首选。
其他回答
请看上面的两个答案。我只是想补充一下,想要做向量化的原因是,这些操作可以很容易地由超级计算机和多处理器并行执行,从而产生巨大的性能增益。在单处理器计算机上不会有性能提升。
我会将向量化定义为给定语言的一个特性,其中如何遍历某个集合的元素的责任可以从程序员委托给语言提供的一些方法(例如,显式的元素循环)。
我们为什么要这么做呢?
Code readeability. For some (but not all!) cases operating over the entire collection at once rather than to its elements is easier to read and quicker to code; Some interpreted languages (R, Python, Matlab.. but not Julia for example) are really slow in processing explicit loops. In these cases vectorisation uses under the hood compiled instructions for these "element order processing" and can be several orders of magnitude faster than processing each programmer-specified loop operation; Most modern CPUs (and, nowadays, GPUs) have build-in parallelization that is exploitable when we use the vectorisation method provided by the language rather than our self-implemented order of operations of the elements; In a similar way our programming language of choice will likely use for some vectorisation operations (e.g. matrix operations) software libraries (e.g. BLAS/LAPACK) that exploit multi-threading capabilities of the CPU, another form of parallel computation.
请注意,对于第3点和第4点,一些语言(特别是Julia)允许这些硬件并行也使用程序员定义的顺序处理(例如for循环),但这是自动发生的,在使用语言提供的向量化方法时。
现在,虽然向量化有许多优点,但有时算法使用显式循环比向量化更直观地表达(可能我们需要求助于复杂的线性代数运算、单位和对角矩阵……所有这些都是为了保留我们的“向量化”方法),如果使用显式排序形式没有计算上的缺点,那么这个应该是首选。
它指的是在一个步骤中对一个数字列表(或“向量”)进行单一数学运算的能力。你经常在Fortran中看到它,因为它与科学计算有关,而科学计算又与超级计算有关,向量化算术就是在那里首次出现的。如今,几乎所有的桌面cpu都提供某种形式的向量化算法,比如通过英特尔的SSE等技术。gpu还提供了一种向量化算法。
向量化是将标量程序转换为矢量程序的术语。向量化程序可以从一条指令运行多个操作,而标量程序一次只能对操作数对进行操作。
从维基百科:
标量的方法:
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];
}
许多cpu都有“矢量”或“SIMD”指令集,可以同时对两个、四个或更多的数据应用相同的操作。现代x86芯片有SSE指令,许多PPC芯片有“Altivec”指令,甚至一些ARM芯片有一个矢量指令集,称为NEON。
“矢量化”(简化)是重写循环的过程,这样它就不是处理数组中的单个元素N次,而是同时处理数组中的4个元素N/4次。
我选择4是因为它是现代硬件最可能直接支持的32位浮点数或整型数。
向量化与循环展开的区别: 考虑以下非常简单的循环,它添加两个数组的元素并将结果存储到第三个数组中。
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”是一个占位符,用于任何内在(s)你的编译器用来指定向量指令。
术语:
请注意,大多数现代提前编译器都能够像这样自动向量化非常简单的循环,这通常可以通过compile选项启用(在现代C和c++编译器中,默认情况下是完全优化的,如gcc -O3 -march=native)。openmp# pragma omp simd有时有助于提示编译器,特别是对于“约简”循环,例如对FP数组求和,其中向量化需要假装FP数学是关联的。
更复杂的算法仍然需要程序员的帮助来生成良好的矢量代码;我们称之为手动矢量化,通常使用像x86 _mm_add_ps这样的intrinsic来映射到单个机器指令,例如在Intel cpu上的SIMD前缀和或如何使用SIMD计算字符出现次数。或者甚至使用SIMD短的非循环问题,如最疯狂的最快方式将9字符数字转换为int或无符号int或如何将二进制整数转换为十六进制字符串?
The term "vectorization" is also used to describe a higher level software transformation where you might just abstract away the loop altogether and just describe operating on arrays instead of the elements that comprise them. e.g. writing C = A + B in some language that allows that when those are arrays or matrices, unlike C or C++. In lower-level languages like that, you could describe calling BLAS or Eigen library functions instead of manually writing loops as a vectorized programming style. Some other answers on this question focus on that meaning of vectorization, and higher-level languages.