如何确定向量长度以确保向量化过程中没有向量依赖性?

Posted

技术标签:

【中文标题】如何确定向量长度以确保向量化过程中没有向量依赖性?【英文标题】:How to determine vector length to ensure no vector dependency during vectorization? 【发布时间】:2020-03-02 00:36:40 【问题描述】:

对于像这个例子这样的情况

for (int i = 16; i < n; i++) 
    a[i] += a[i-16];

如何确定向量长度以确保可以对这个循环进行向量化? 以下是正确的方法吗?

// Determine target cpu architecture's vector register bit-size
// E.g., Intel AVX-512 has 512-bit vector registers
int register_size = 512

// Modern machines are 8 bits
int byte_size = 8

// Determine array type size
int my_array[n];
auto array_type_size = sizeof(int) * byte_size   // 4 bytes * 8 bits = 32 bits

// Divide register size by array type size
auto vector_length = register_size / array_type_size    // = 16

这意味着在英特尔 AVX-512 上对 int 类型的数组进行向量化会导致寄存器中的向量长度为​​ 16,从而使上述示例可以安全地进行向量化。

这个方法正确吗?如果是这样,有没有办法在这个架构上使用更短的向量?例如,强制一个长度为 4 的向量,以便下面的示例可以向量化

for (int i = 4; i < n; i++) 
    a[i] += a[i-4];

【问题讨论】:

如果代码速度提高 1% 不是那么重要,那就留给编译器吧。 你打算使用#pragma omp simd吗?此类指令旨在向编译器提供有关矢量化的提示,并且它们具有针对这种情况的子句。 正如@JérômeRichard 所说,使用 omp simd 并表达您知道的信息(数组索引空间中依赖项的长度),然后让编译器完成剩下的工作。您不必担心机器架构。 【参考方案1】:

英特尔提供了一系列 SIMD 功能。您可以使用从 64 位 mmx 寄存器到 512 zmm 寄存器。您也可以很好地使用这些寄存器的下半部分:您可以使用 256 位 ymm,甚至可以使用别名的下半部分并使用 128 位 xmm。无论您的循环范围或大小如何,您的编译器都会在发布模式下尽可能多地对循环进行矢量化。如果您想自己执行此操作,您可以编辑编译器标志或编写自己的程序集,以实现小幅但明显的速度提升。要“强制”编译器以某种方式向量化,将更改编译器标志以禁止使用 AVX-512,或者可能使用编译器将在其文档中包含的一些预处理器指令。 不使用矢量化的整个寄存器没有固有的问题。

【讨论】:

以上是关于如何确定向量长度以确保向量化过程中没有向量依赖性?的主要内容,如果未能解决你的问题,请参考以下文章

如何在python中创建一个N次方的特征向量?

如何使用向量化代码从 MATLAB 中的两个向量生成所有对?

用Word2Vec词向量化的数据训练Seq2Seq翻译模型的问题?

语音处理中的向量量化解释

如何克服icc中的“存在向量依赖”

向量化计算numpy中一组点的所有单位向量