在 std::vector 上的 Visual Studio 2012 express 中的自动矢量化没有发生
Posted
技术标签:
【中文标题】在 std::vector 上的 Visual Studio 2012 express 中的自动矢量化没有发生【英文标题】:Auto-Vectorization in Visual Studio 2012 express on std::vector is not happening 【发布时间】:2016-10-17 06:28:35 【问题描述】:我有一个简单的程序,其中我有 3 个 std::vector 并在 for 循环中使用它们。在启用编译标志后,我正在测试这些循环是否被优化。但是Visual Studio显示由于1200原因导致循环未矢量化。我的示例代码如下。
#include <iostream>
#include <vector>
#include <time.h>
int main(char *argv[], int argc)
clock_t t=clock();
int tempSize=100;
std::vector<double> tempVec(tempSize);
std::vector<double> tempVec1(tempSize);
std::vector<double> tempVec2(tempSize);
for(int i=0;i<tempSize;i++)
tempVec1[i] = 20;
tempVec2[i] = 30;
for(int i=0,imax=tempSize;i<imax;i++)
tempVec[i] = tempVec1[i] + tempVec2[i];
t =clock()-t; // stop the clock
std::cout <<"Time in millisecs = " << t/double(CLOCKS_PER_SEC) << std::endl;
return 0;
下面是使用启用选项“/Qvec-report:2”的代码编译的输出。
2> --- 分析函数:main 2> d:\test\ssetestonvectors\main.cpp(12) : info C5002: loop not vectorized due to reason '1200' 2> d:\test\ssetestonvectors\main.cpp(18) : info C5002: loop not vectorized due to reason '1200'
当我在 msdn 页面上看到错误代码 1200 时: https://msdn.microsoft.com/en-us/library/jj658585.aspx 它指定错误代码1200是由于“循环包含循环携带的数据依赖”
我无法理解这个循环是如何包含它的。我有一些需要优化的代码,以便它可以使用 Visual Studio 的自动矢量化功能,以便可以针对 SSE2 进行优化。此代码包含向量操作。所以我无法做到这一点,因为每次 Visual Studio 都会显示一些这样的错误代码。
【问题讨论】:
【参考方案1】:我认为你的问题是:
for(int i=0,imax=tempSize;i<imax;i++)
tempVec[i] = tempVec1[i] + tempVec2[i];
真的是
for(int i=0,imax=tempSize;i<imax;i++)
tempVec.operator[](i) = tempVec1.operator[](i) + tempVec2.operator[](i);
... 并且矢量化器无法查看函数调用的内部。第一个解决方法是:
const double* t1 = &tempVec1.front();
const double* t2 = &tempVec2.front();
double *t = &tempVec.front();
for(int i=0,imax=tempSize;i<imax;i++)
t[i] = t1[i] + t2[i];
问题在于矢量化器看不到 t、t1 和 t2 不重叠。你必须向编译器保证他们不会:
const double* __restrict t1 = &tempVec1.front();
const double* __restrict t2 = &tempVec2.front();
double * __restrict t = &tempVec.front();
for(int i=0,imax=tempSize;i<imax;i++)
t[i] = t1[i] + t2[i];
显然(我希望)使用 __restrict
关键字(它不是标准 C++ 的一部分)意味着这段代码不能移植到其他 C++ 编译器。
编辑:OP 已经澄清,用对at
的调用替换对operator[]
的调用会产生不同的失败消息(尽管可能是因为at
更复杂)。
如果问题不在于函数调用,我的下一个假设是operator []
归结为return this.__begin[i];
之类的东西,并且矢量化器不知道不同的std::vector
s 具有不重叠的内存。如果是这样,最终的代码块仍然是解决方案。
【讨论】:
感谢 Martin 的建议,其实正如你一开始所说的那样 抱歉半点评论。这是错误地完成的。正如您添加的那样,vectorizer 无法查看函数调用,我对此有点怀疑,因为如果我使用tempVec.at(i) = tempVec1.at(i) + tempVec2.at(i)
而不是 tempVec[i] = tempVec1[i] + tempVec2[i];
,那么编译器将通过函数调用导致的原因为 500。您建议的代码可用于优化。您能否建议我可以实际学习转换代码以进行自动矢量化的任何链接。再次感谢您的回答。
有趣。请注意,1200 的文档说调用“fn()”将抑制矢量化。也许问题只是 std::vector 内部有一个非限制指针,而矢量化器不知道它必须是唯一的(因此创建限制指针是解决它的方法)/
我不知道如何转换代码以进行自动矢量化,除了 a) 启用警告; b) 阅读警告信息; c) 弄清楚它们的意思。您可能会发现新版本的 VS 会有所帮助。
哦!我犯了一个多么愚蠢的错误,我没有注意到 fn() 函数调用。顺便说一句,感谢您的建议,我也会尝试新版本的 VS。【参考方案2】:
自动矢量化是 MSVC 的一项相当新的功能,您使用的是旧版本的 MSVC。所以它远非完美。 Microsoft 知道这一点,因此他们决定仅在绝对安全的情况下对代码进行矢量化处理。
特定的错误消息有点简洁。实际上,它应该说“循环可能包含循环携带的数据依赖”。由于 MSVC 无法证明它们不存在,因此它不会向量化。
【讨论】:
感谢 MSalters 调查问题。当我读到 Visual Studio 的自动矢量化功能时,他们已经在 int Visual Studio 2012 中引入了它,我正在使用它。他们写了一系列关于它的博客文章 (blogs.msdn.microsoft.com/nativeconcurrency/2012/04/12/…)。 可能是在旧版本的 VS 中信息量较少。以上是关于在 std::vector 上的 Visual Studio 2012 express 中的自动矢量化没有发生的主要内容,如果未能解决你的问题,请参考以下文章
如何为 std::vector 复制或使用隐式缩小转换禁用 Visual Studio 警告 C4244
Visual Studio 中的 std::packaged_task 错误?