Visual Studio 2017 循环自动矢量化问题
Posted
技术标签:
【中文标题】Visual Studio 2017 循环自动矢量化问题【英文标题】:Visual Studio 2017 loop auto-vectorization issue 【发布时间】:2018-10-29 09:57:57 【问题描述】:我正在尝试使用 Visual C++ 2017 自动矢量化器将以下循环矢量化 (/arch:AVX2):
void fun(char* data, char* threshold, char* output, int64_t len)
// Assumes output filled with 0
for (int64_t c = 0, mm = len; c < mm; ++c)
output[c] = (data[c] < threshold[c])
? (threshold[c] - data[c])
: output[c];
此代码用于比较2个数组(数据和阈值),如果数据
此循环不会自动矢量化:
info C5002:由于原因“1100”,循环未矢量化
含义:循环包含控制流,例如“if”或“?”。
好的,我明白了,我需要重写我的循环,以便删除控制流或为编译器简化它。但是:
GCC 对它进行矢量化没有问题
如果我以这种方式更改代码,Visual Studio 接受对其进行矢量化:
代码:
for (int64_t c = 0, mm = len; c < mm; ++c)
output[c] = (data[c] < threshold[c])
? (char)(threshold[c] - data[c])
: output[c];
为什么这个 (char) cast 会改变 Visual Studio 自动矢量化器的任何内容?这是自动矢量化器的错误还是我遗漏了什么?
此外,如果我将输出数组的类型从 char 更改为 int,我无法再让 Visual Studio 对我的循环进行矢量化,而 GCC 可以:
void fun(char* data, char* threshold, int* output, int64_t len)
// Assumes output filled with 0
for (int64_t c = 0, mm = len; c < mm; ++c)
output[c] = (data[c] < threshold[c])
? (int)(threshold[c] - data[c])
: output[c];
与 GCC 相比是否缺少 Visual Studio 2017 自动矢量化器?还是我在尝试做一些我不应该做的事情?
【问题讨论】:
您是否检查了程序集以确保它真的是矢量化的? 是的,VS vectorizer 比 gcc 和 clang 的差很多,而且远远落后于 Intel。 @MatthieuBrucher 是的,我检查过,当我投射时它真的是矢量化的 【参考方案1】:这只是一个错失的优化机会。 VS 矢量化器自 2012 年以来有了很大的改进,但与 gcc 或 clang 相比仍然相当缺乏。请记住,他们的编译器基于古老的代码库,例如直到最近,他们甚至都没有SSA 的代表。
【讨论】:
总是比较所有编译器,尤其是 icc,因为它提供了非常详细的矢量化报告:godbolt.org/g/eNfR2A 是的,我想我需要承认我无法使用 VisualStudio 对我的代码进行矢量化(我给出的示例是我需要矢量化的真实代码的一个更简单的版本)。无论如何,感谢@Trass3r 为我提供了这个我不知道的惊人网站。以后会省很多时间! 问题在于这些优化依赖于识别代码模式。微小的变化可以产生很大的不同:bugs.llvm.org/show_bug.cgi?id=39597。 Godbolt确实是传奇!以上是关于Visual Studio 2017 循环自动矢量化问题的主要内容,如果未能解决你的问题,请参考以下文章
Visual Studio 的循环矢量化(手动和自动)都有哪些资源?
在 std::vector 上的 Visual Studio 2012 express 中的自动矢量化没有发生
如何在 Visual Studio 2015(用于 C++)中仅禁用 SIMD 自动矢量化优化?
在 Blend for Visual Studio 2013 中导入为矢量图形