269

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

4

8 回答 8

316

许多 CPU 具有“向量”或“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”是编译器用来指定向量指令的任何内在函数的占位符。请注意,一些编译器能够自动矢量化像这样的非常简单的循环,这通常可以通过编译选项启用。更复杂的算法仍然需要程序员的帮助才能生成好的矢量代码。

于 2009-09-14T15:12:00.813 回答
45

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

来自维基百科

标量方法:

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];
}
于 2009-09-14T15:13:43.837 回答
18

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

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

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

尽管有大量的解释,这里是向量化在NUMPY文档页面中的定义

矢量化描述了代码中没有任何显式循环、索引等 - 当然,这些事情只是在优化的、预编译的 C 代码中“在幕后”发生。矢量化代码有很多优点,其中包括:

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

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

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

  4. 矢量化导致更多“Pythonic”代码。如果没有矢量化,我们的代码将充满低效且难以阅读的 for 循环。

于 2017-05-02T04:34:34.630 回答
13

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

于 2009-09-14T15:09:02.137 回答
13

简单来说,向量化意味着优化算法,使其可以在处理器中使用 SIMD 指令。

AVX、AVX2 和 AVX512 是指令集(intel),它们在一条指令中对多个数据执行相同的操作。例如。AVX512 意味着您一次可以操作 16 个整数值(4 个字节)。这意味着如果你有 16 个整数的向量,并且你想在每个整数中将该值加倍,然后将 10 加到它上面。您可以将值加载到通用寄存器 [a,b,c] 16 次并执行相同的操作,或者您可以通过将所有 16 个值加载到 SIMD 寄存器 [xmm,ymm] 并执行一次操作来执行相同的操作。这可以加快矢量数据的计算速度。

在矢量化中,我们利用这一优势,通过重构我们的数据,以便我们可以对其执行 SIMD 操作并加速程序。

矢量化的唯一问题是处理条件。因为条件分支了执行流程。这可以通过掩蔽来处理。通过将条件建模为算术运算。例如。如果我们想在值大于 100 的情况下加 10。我们也可以。

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,它可以让你使用 pragma 对代码进行矢量化。我认为这是一个很好的起点。OpenACC 也是如此。

于 2018-12-20T17:05:16.267 回答
8

英特尔人我认为很容易掌握。

矢量化是将算法从一次对单个值进行操作转换为一次对一组值进行操作的过程。现代 CPU 直接支持将单个指令应用于多个数据 (SIMD) 的向量运算。

例如,具有 512 位寄存器的 CPU 可以保存 16 个 32 位单精度双精度并执行单次计算。

比一次执行一条指令快 16 倍。将此与线程和多核 CPU 相结合,可带来数量级的性能提升。

链接https://software.intel.com/en-us/articles/vectorization-a-key-tool-to-improve-performance-on-modern-cpus

在 Java 中,可以选择将其包含在 2020 年的 JDK 15 中或 2021 年的 JDK 16 中。请参阅此官方问题

于 2020-04-11T01:20:55.140 回答
1

希望你一切都好!

向量化是指将缩放器实现(其中单个操作一次处理单个实体)转换为向量实现(其中单个操作同时处理多个实体)的所有技术。

矢量化是指一种技术,借助它我们可以优化代码以有效地处理大量数据。在 NumPy、pandas 等科学应用程序中看到矢量化的应用,您也可以在使用 Matlab、图像处理、NLP 等时使用此技术。总体而言,它优化了程序的运行时和内存分配。

希望你能得到你的答案!

谢谢你。

于 2022-02-02T09:45:05.057 回答
-5

请参阅上面的两个答案。我只是想补充一点,想要进行矢量化的原因是这些操作可以很容易地由超级计算机和多处理器并行执行,从而获得很大的性能提升。在单处理器计算机上不会有性能提升。

于 2009-09-14T15:13:11.607 回答