Visual studio无法矢量化
Visual studio fails to vectorise
我尝试在VS2013中编译以下代码
template <class T>
void assignment(T* result, size_t sz, const T x)
{
for (size_t i = 0; i < sz; i++)
result[i] = x;
}
和编译器无法用以下消息向量化代码。
info C5002: loop not vectorized due to reason '1104'
,而下面的代码可以
void discountFactor(double* result, const double* r, double t, size_t sz)
{
for (size_t i = 0; i < sz; i++)
result[i] = -r[i] * t;
for (size_t i = 0; i < sz; i++)
result[i] = exp(result[i]);
}
谁能给我解释一下1104的原因是什么? 正如其他人所说,这些类型的优化在MSDN上有很好的文档记录。事实上,这里有一个很好的例子。下面是代码片段:
int code_1104(int *A, int *B)
{
// When it vectorizes a loop, the compiler must 'expand' scalar
// variables to a vector size such that they can fit in
// vector registers. Code 1104 is emitted when the compiler
// cannot 'expand' such scalars.
// In this example, we try to 'expand' x to be used in the
// vectorized loop. However, there is a use of 'x'
// beyond the loop body, which prohibits this expansion.
// To resolve this, try to limit scalars to be used only in
// the loop body and not beyond, and try to keep their types
// consistent with the loop types.
int x;
for (int i=0; i<1000; ++i)
{
x = B[i];
A[i] = A[i] + x;
}
return x;
}
我的解释(老实说,他们只是猜测):第二个例子之所以有效,是因为result
是原始数据类型(double *
),即使它在循环的作用域之外,也可以很容易地修改。
示例在其注释中告诉…
// When it vectorizes a loop, the compiler must 'expand' scalar
// variables to a vector size such that they can fit in
// vector registers.
取决于你如何调用你的模板函数assignment
,你的T
在第一个例子中可能是任何。包含了一个不适合寄存器的类型。因此,我假设编译器不能自动向量化您的for
-循环。
编译器不能很好地确定哪些变量被用作只读。您必须确保向量化循环使用局部变量的const副本。考虑下面的代码:
#include <iostream>
using std::cout;
using std::endl;
using std::cin;
void doIt(double* src, double* dst, double factor, int sz) {
for (int i = 0; i < sz; ++i) { // loop vectorized
dst[i] += src[i] * factor;
}
}
int main() {
static const int SZ = 1024;
double sum = 0.0;
double factor;
double initial;
double source[SZ];
double destination[SZ];
cin >> factor;
for (int i = 0; i < SZ; ++i) { // 22, reason 1200, data dependency expected
cin >> source[i];
}
cin >> initial;
for (int i = 0; i < SZ; ++i) { // 27, reason 1104
destination[i] += source[i] * factor;
}
doIt(source, destination, factor, SZ); // 31, no problem
return 0;
}
这里doIt
中的循环是由编译器向量化的,而main
中的循环则不是。
为什么?
因为factor
不是const变量,并且在从第27行开始的循环中,它可以被修改(尽管它显然不是)。
为什么doIt
不引起问题?
因为factor是按值传递的,而不是按引用传递的。
修复吗?
使因子为const变量
#include <iostream>
using std::cout;
using std::endl;
using std::cin;
void doIt(double* src, double* dst, double factor, int sz) {
for (int i = 0; i < sz; ++i) { // loop vectorized
dst[i] += src[i] * factor;
}
}
double GetFactor() {
double ret;
cin >> ret;
return ret;
}
int main() {
static const int SZ = 1024;
double sum = 0.0;
const double factor = GetFactor();
double initial;
double source[SZ];
double destination[SZ];
for (int i = 0; i < SZ; ++i) { // 22, reason 1200, data dependency expected
cin >> source[i];
}
cin >> initial;
for (int i = 0, mysz=SZ; i < mysz; ++i) { // no problem
destination[i] += source[i] * factor;
}
doIt(source, destination, factor, SZ); // no problem
return 0;
}
很好,但这和我有什么关系?
我怀疑你的模板函数被内联了,本质上与第一个例子中第27行的循环相同。尝试更改传递给模板函数的变量x
,如下所示:
:
assignment(bob, sz, x);
新:const double copyx = x;
assignment(bob, sz, copyx);
相关文章:
- 普通环路未使用gcc 4.8.5自动矢量化
- 阵列火矢量化
- 使用矢量化c++的矩阵乘法
- 循环中标量乘积的自动矢量化
- 如何在clang++中禁用矢量化
- 加权外积的矢量化
- 手动矢量化/SSE 用于 C++ 中的复杂问题
- 包含比较的循环的自动矢量化
- pcl_ros::transformPointCloud的矢量化
- 迭代卡拉苏巴算法在C++中使用OpenACC并行化和矢量化
- (如何)我可以使用openmp矢量化"std::complex<double>"吗?
- C 矩阵乘法自动矢量化
- 矢量化 :乘以_m256i元素
- 是否可以使用 SSE 对此嵌套进行矢量化?
- 为什么内联函数中的循环无法正确自动矢量化
- 是否保证 OpenMP 矢量化
- AVX,SSE总和比gcc自动矢量化慢
- 嵌套矢量化 OpenMP 循环,在最内层循环中具有多行代码
- 模乘法的矢量化
- Visual studio无法矢量化