Visual Studio 2012 Express std::vector 中的自动矢量化未发生
Auto-Vectorization in Visual Studio 2012 express on std::vector is not happening
我有一个简单的程序,其中有 3 个 std::vector 并在 for 循环中使用它们。启用编译标志 ON 后,我正在测试这些循环是否已优化。但是 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) : 信息 C5002: 由于“1200”原因循环未矢量化
2> d:\test\ssetestonvectors\main.cpp(18) : 信息 C5002: 由于 '1200'
原因,循环未矢量化
当我在 msdn 页面上看到错误代码 1200 时:
https://msdn.microsoft.com/en-us/library/jj658585.aspx
它指定错误代码 1200 是由于 "Loop contains loop carried data dependence"
我无法理解这个循环是如何包含它的。我有一些代码需要优化,以便它可以使用 Visual studio 的自动矢量化功能,从而可以针对 SSE2 进行优化。此代码包含向量运算。所以我无法这样做,因为每次 visual studio 都显示这样的错误代码。
自动矢量化是 MSVC 的一项相当新的功能,而您使用的是旧版本的 MSVC。所以它远非完美。微软知道这一点,所以他们决定只在绝对安全的情况下才对代码进行矢量化。
特定的错误消息有点简洁。实际上,它应该是 "Loop might contain loop-carried data dependence"。由于 MSVC 无法证明它们不存在,因此它不会矢量化。
我认为你的问题是:
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 已阐明将对 operator[]
的调用替换为对 at
的调用会产生不同的失败消息(尽管 可能是因为at
更复杂)。
如果问题不在于函数调用,我的下一个假设是 operator []
归结为 return this.__begin[i];
之类的东西,向量化器不知道不同的 std::vector
有非重叠内存。如果是这样,最后的代码块仍然是解决方案。
我有一个简单的程序,其中有 3 个 std::vector 并在 for 循环中使用它们。启用编译标志 ON 后,我正在测试这些循环是否已优化。但是 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) : 信息 C5002: 由于“1200”原因循环未矢量化 2> d:\test\ssetestonvectors\main.cpp(18) : 信息 C5002: 由于 '1200'
原因,循环未矢量化当我在 msdn 页面上看到错误代码 1200 时: https://msdn.microsoft.com/en-us/library/jj658585.aspx 它指定错误代码 1200 是由于 "Loop contains loop carried data dependence"
我无法理解这个循环是如何包含它的。我有一些代码需要优化,以便它可以使用 Visual studio 的自动矢量化功能,从而可以针对 SSE2 进行优化。此代码包含向量运算。所以我无法这样做,因为每次 visual studio 都显示这样的错误代码。
自动矢量化是 MSVC 的一项相当新的功能,而您使用的是旧版本的 MSVC。所以它远非完美。微软知道这一点,所以他们决定只在绝对安全的情况下才对代码进行矢量化。
特定的错误消息有点简洁。实际上,它应该是 "Loop might contain loop-carried data dependence"。由于 MSVC 无法证明它们不存在,因此它不会矢量化。
我认为你的问题是:
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 已阐明将对 operator[]
的调用替换为对 at
的调用会产生不同的失败消息(尽管 可能是因为at
更复杂)。
如果问题不在于函数调用,我的下一个假设是 operator []
归结为 return this.__begin[i];
之类的东西,向量化器不知道不同的 std::vector
有非重叠内存。如果是这样,最后的代码块仍然是解决方案。