【发布时间】:2014-03-20 20:55:06
【问题描述】:
下面的代码是导致我在代码中看到的错误的简化案例。当我手动调用A(const A&) 的构造函数时,一切都很好,但是当我尝试将一个vector<A> 复制到另一个时,我在A(const A& in) : vec(in.vec) {} 行出现段错误。
为什么会发生这种情况,我该如何处理我的代码?
编辑:所以我通过 @mpromonet 添加了代码,它现在运行完成,但是 1. 它要慢得多(超过 3 倍)和 2. 当我使用 -pg 编译以找出原因时,调用 _mm256_add_pd 时出现段错误。
#include <immintrin.h>
#include <vector>
using std::vector;
struct A {
union {
struct {
double a, b, c;
};
__m256d vec;
};
A() : a(0), b(0), c(0) {}
A(const A& in) : vec(in.vec) {}
};
int main() {
vector<A> e(10);
vector<A> b;
b = e;
}
编辑:
这段代码在我的程序中占了大部分时间。使用g++ --std=c++11 -ffast-math -march=native -O3 -fno-inline -g -pg 编译。请参阅下面的调用图。我有一个Electron 对象数组,其中包含两个用__attribute__((aligned(32))) 声明的Vector 对象。为了使数组对齐,我这样做了
Electron* data_orig = new Electron[s+3];
Electron* data = (Electron*)((void*)data_orig + 64 - (size_t)data_orig % 64);
没有 AVX
struct Vector {
double x;
double y;
double z;
Vector(double a, double b, double c) :
x(a), y(b), z(c)
{}
Vector(const Vector& u) :
x(u.x), y(u.y), z(u.z)
{}
Vector(const UnitVector& u);
Vector operator*=(const double m) { x*=m; y*=m; z*=m; return *this; }
Vector operator+=(const Vector& in) {
x+=in.x; y+=in.y; z+=in.z;
return *this;
}
ostream& operator<<(ostream& os) {
os << "x:" << x << " y:" << y << " z:" << z;
return os;
}
};
Vector::Vector(const UnitVector& u) :
x(u.x*u.mag), y(u.y*u.mag), z(u.z*u.mag)
{}
使用 AVX
struct Vector {
union {
struct {
double x;
double y;
double z;
};
__m256d vec __attribute__ ((aligned (32)));
};
Vector(double a, double b, double c) :
x(a), y(b), z(c)
{}
Vector(const Vector& in) : vec(in.vec) {}
//: x(in.x), y(in.y), z(in.z) {}
Vector(const UnitVector& u);
Vector operator*=(const double m) {
vec = _mm256_mul_pd(vec, _mm256_set1_pd(m));
return *this;
}
Vector operator+=(const Vector& in) {
vec = _mm256_add_pd(vec, in.vec);
return *this;
}
ostream& operator<<(ostream& os) {
os << "x:" << x << " y:" << y << " z:" << z;
return os;
}
};
Vector::Vector(const UnitVector& u) { vec = _mm256_mul_pd(u.vec, _mm256_set1_pd(u.mag));}
【问题讨论】:
-
我认为这是因为向量如何处理内存 - 可能存在指针未对齐
-
对象肯定没有对齐。 有点 可怕的是,较新的编译器有时会在所有情况下发出未对齐的访问。因此,虽然它不会崩溃,但您可能会受到性能影响。最糟糕的是,你甚至都不知道。
-
看起来
__m256d只是double和__attribute__((__vector_size__(32)))上的typedef -
@Mysticial:如果内存对齐,
vmovups和vmovaps一样快;唯一的区别是当数据未对齐时它不会崩溃。使用vmovaps的唯一原因是强制执行对齐。 -
@StephenCanon 是的。这就是我想要的强制执行。但是最新的 VS 和 ICC 编译器总是使用
vmovups。所以我什至不知道什么时候出现了偏差。 :(
标签: c++ g++ stdvector intrinsics avx