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 中导入为矢量图形

Visual Studio 2017 (.NET Core) 中的自动版本控制

如何禁用自动隐藏解决方案资源管理器(Visual Studio 2017)