Сигнал EXC_BAD_ACCESS при попытке инициализировать переменную-член класса __m128 - PullRequest
1 голос
/ 23 июня 2011

Я использую Apple GCC 4.2.1 , и я наткнулся на странную проблему со следующим кодом ... Я всегда получаю исключение EXC_BAD_ACCESS при попытке инициализировать __ m128 переменная члена класса.К сожалению, следующий упрощенный код работает в тестовом приложении, но, может быть, вы все еще можете помочь мне найти корень этой проблемы?

Я не понимаю причину EXC_BAD_ACCESS исключения - __m128 тип не является указателем, и все другие MyClass члены инициализируются и доступны без каких-либо проблем, нет признаков повреждения стека / кучи, все работает, если я использую локальные переменные и нет проблемпод MSVC ... Может, что-то не так с выравниванием?

Пожалуйста, помогите!

class MyClass
{
    public:
    // lots of members
    __m128 vect;

    MyClass()
    {
        vect = _mm_setr_ps (0.f, 0.f, 0.f, 10.0f); // Program received signal: “EXC_BAD_ACCESS”.
    }

    void iniialize()
    {
        __m128 localVector = _mm_setr_ps (0.f, 0.f, 0.f, 10.0f); // No problems
        vect = localVector; // Program received signal: “EXC_BAD_ACCESS”.
    }
};

Ответы [ 3 ]

2 голосов
/ 23 июня 2011

В глубине души: я бы сказал, что проблемы с выравниванием

Особенно в той части, где написано «много членов»

Посмотрите на __attribute__ aligned

0 голосов
/ 23 июня 2011

Если проблема заключается в смещении стека, следует проверить параметр командной строки -mstackrealign, см. Документацию GCC . Это решило мои проблемы с целью MinGW. См. Также обсуждение выравнивание по стеку . Наконец, вы можете обновить GCC до более новой версии.

С другой стороны, если вы распределяете объекты динамически, вы должны убедиться, что память выровнена, как заметил Пол. Существуют такие методы, как _mm_malloc и _mm_free, которые могут помочь вам в этом.

0 голосов
/ 23 июня 2011

gcc автоматически выровняет __m128 членов, если объект создан в стеке, но для объектов, выделенных с помощью new, вы попадаете в зависимость от распределителя памяти, который в Linux обычно выровнен только на 8 байт.Вам может потребоваться переопределить оператор new для вашего класса, чтобы он вызывал posix_memalign , чтобы вы всегда получали объекты, выровненные по 16 байтам.

Сказав это, если вы попадаете в SSEПосле оптимизации кода вам может потребоваться переоценить то, как вы делаете кодирование - поскольку производительность обычно является стимулом для оптимизации SIMD, вам может потребоваться работать на несколько более низком уровне, чем классы C ++, - обычно вы просто хотите работать однородно на больших порцияхсмежные данные, т.е. 1D или 2D массивы.

...