我知道只有在被访问的对象在内存中是连续的时才能进行矢量化。我创建了一个具有指针的结构,然后我创建了这个结构的向量,并确保对象向量内的指针指向连续的数据块,我将它们设置为指向具有相同大小的double向量中的元素。
#include <iostream>
#include <vector>
struct Vec {
Vec() {}
double* a;
};
int main(int argc, char* argv[]) {
std::vector<double> vec_double(10000000, 1.0);
std::vector<Vec> vec_vec(10000000);
for (unsigned i = 0; i < 10000000; ++i)
vec_vec[i].a = &(vec_double[i]);
// Why is this loop not vectorized
for (unsigned i = 0; i < 10000000; ++i)
vec_double[i] += *(vec_vec[i].a);
double sum = 0.0;
for (unsigned i = 0; i < 10000000; ++i)
sum += vec_double[i];
std::cout << sum << std::endl;
return 0;
}
然而,即使使用O3优化,第16行的循环也没有进行矢量化。有人可以解释为什么会发生这种情况吗?
答案 0 :(得分:3)
这里只是猜测,但是当看到这个特定的循环时,编译器不知道vec_vec[i].a
指向vec_vec[i+1].a
旁边的内存位置。因此,如果不单独解除引用每个.a
成员,则无法进行计算。
当看到上面的循环时,它可以知道。但如果它会这样做,它也可以查看下面的循环,计算最终结果并打印出来。
答案 1 :(得分:0)
您应该首先从迭代器获取原始指针。与此vec_vec.begin()_Ptr
和vec_double.begin()._Ptr
一样。使用遗留的那些指针。最后声明它没有别名的方法。像这样__declspec(noalias)
。它应该在Windows上使用msvc完成这个技巧。我不认为GCC有noalias属性。