Почему присвоение элементу массива AVX-Vector-wrapper-class-object-array вызывает ошибки нарушения доступа? - PullRequest
2 голосов
/ 29 марта 2012

Я пытаюсь сделать кое-что векторное и написал оболочку для типа данных 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 Ответ

3 голосов
/ 29 марта 2012

Вероятно, это проблема выравнивания .__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);

должно работать.

EDIT : после попытки выполнить это в Windowsс GCC 4.6.1 (переключатель компилятора -march=corei7-avx) кажется new не соответствует требованиям выравнивания.Изменение нового вызова на использование _aligned_malloc работает.

...