Почему присвоение элементу массива AVX-Vector-wrapper-class-object-array вызывает ошибки нарушения доступа?
Я пытаюсь сделать кое-что векторное и написал оболочку для типа данных m256d из immintrin.h для использования перегруженных операторов. Следующий пример должен дать вам основную идею.
Определение класса
#include <immintrin.h>
using namespace std;
class vwrap {
public:
__m256d d;
vwrap(void) {
this->d = _mm256_set_pd(0.0,0.0,0.0,0.0);
}
void init (const double &a, const double &b, const double &c) {
this->d = _mm256_set_pd(0.0,c,b,a);
}
};
Массив объектов vwrap
Давайте представим массив vwrap, который выделяется динамически:
vwrap *a = (vwrap*) malloc(sizeof(vwrap)*2);
Ошибки нарушения доступа
Использование функции объекта vwrap, который содержит функцию-набор mm256... провоцирует ошибку нарушения доступа.
a[0].init(1.3,2.3,1.2);
То же самое происходит с назначением d с помощью функции набора mm256 (назначение другого объекта m256d также не работает):
a[0].d = _mm256_set_pd(1,2,3,4);
Копирование данных из другого объекта тоже не работает.
vwrap b;
a[0].d = b.d;
Материал, который работает
Объектом m256d можно манипулировать без проблем:
a[0].d.m256d_f64[0] = 1.0;
a[0].d.m256d_f64[1] = 2.0;
a[0].d.m256d_f64[2] = 3.0;
a[0].d.m256d_f64[3] = 4.0;
Назначения работают в случае обычного экземпляра класса:
vwrap b,c;
__mm256d t = _mm256_set_pd(1,2,3,5);
b.d = _mm256_set_pd(1,2,3,4);
b.d = t;
b.d = c.d;
Я не понимаю проблемы. Почему я не могу использовать функции _mm256 (или назначить m256d-объект) в случае массива классов? Моя единственная идея - избегать использования функций mm256 и напрямую манипулировать двойными значениями. Но это не то, что я намеренно хотел сделать.
1 ответ
Это, скорее всего, проблема с выравниванием. __m256d
необходимо выровнять по 32 байтовым границам. Вы не должны использовать malloc
когда выравнивание является проблемой, используйте new
или выровненный malloc
,
Переменные, выделенные в стеке, работают правильно: компилятор правильно их выравнивает, потому что знает, что они должны быть выровнены. Принимая во внимание, когда вы звоните malloc
, среда выполнения не знает, что вы планируете хранить в памяти, которую она вам дает. Поэтому вам нужно явно запросить выравнивание, используя выровненный malloc
или используйте распределение с учетом типа, что new
для.
изменения
vwrap *a = (vwrap*) malloc(sizeof(vwrap)*2);
в
vwrap *a = new vwrap[2];
vwrap *a = (vwrap*) _aligned_malloc(sizeof(vwrap)*2, 32);
должно сработать.
РЕДАКТИРОВАТЬ: после того, как попробовать это в Windows с GCC 4.6.1 (переключатель компилятора -march=corei7-avx
) похоже на то new
не соблюдает требования выравнивания. Изменение нового вызова на использование _aligned_malloc
работает.