现在好几次,我在matlab,fortran ......中遇到过这个术语......但是我从来没有找到解释是什么意思,它有什么作用?所以我在这里问,什么是矢量化,例如,“循环是矢量化的”是什么意思。 ?

有帮助吗?

解决方案

许多CPU都有“向量”或“SIMD”或“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]);

where addFourThingsAtOnceAndStoreResult&quot;是一个占位符,用于编译器用于指定向量指令的任何内在函数。请注意,某些编译器能够自动向量化非常简单的循环,这通常可以通过编译选项启用。更复杂的算法仍需要程序员的帮助才能生成良好的矢量代码。

其他提示

矢量化是将标量程序转换为矢量程序的术语。向量化程序可以从单个指令运行多个操作,而标量只能同时对一对操作数进行操作。

来自维基百科

标量方法:

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];
}

它指的是在列表上进行单个数学运算的能力 - 或“向量”。 - 一步到位的数字。你经常在Fortran中看到它,因为它与科学计算有关,科学计算与超级计算有关,其中矢量化算法首次出现。如今,几乎所有台式机CPU都通过英特尔的SSE等技术提供某种形式的矢量化算法。 GPU还提供了一种矢量化算法。

矢量化在科学计算中得到了极大的应用,需要高效处理大量数据。

在实际编程应用程序中,我知道它在NUMPY中使用(不确定其他的)。

Numpy(python中的科学计算包),使用 vectorization 来快速操作n维数组,如果使用内置的python选项来处理数组,这通常会更慢。

虽然有大量的解释,但 VECTORIZATION 的定义是 NUMPY DOCUMENTATION PAGE

Vectorization描述了代码中没有任何显式循环,索引等 - 当然,这些事情正在发生在幕后&#8220;在优化的,预编译的C代码中。矢量化代码有许多优点,其中包括:

  1. 矢量化代码更简洁,更易于阅读

  2. 更少的代码行通常意味着更少的错误

  3. 代码更接近标准数学符号 (通常,更容易正确编码数学 构建体)

  4. 矢量化导致更多&#8220; Pythonic&#8221;码。没有 矢量化,我们的代码将被低效率和 难以阅读循环。

简单来说,矢量化意味着优化算法,以便它可以利用处理器中的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也是如此。

见上面的两个答案。我只是想补充一点,想要进行矢量化的原因是这些操作可以很容易地通过超级计算机和多处理器在paraell中执行,从而产生很大的性能提升。在单处理器计算机上,没有性能提升。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top