Выравнивание 16-байтовой памяти с использованием инструкций SSE

я пытаюсь избавиться от невыровненных загрузок и хранилищ для инструкций SSE для моего приложения, заменив

_mm_loadu_ps()

by

_mm_load_ps()

и выделение памяти с помощью:

float *ptr = (float *) _mm_malloc(h*w*sizeof(float),16)

вместо:

float *ptr = (float *) malloc(h*w*sizeof(float))

Однако, когда я печатаю адреса указателя, используя:

printf("%p\n", &ptr)

Получаю вывод:

0x2521d20
0x2521d28
0x2521d30
0x2521d38
0x2521d40
0x2521d48
...

Это не выровнено по 16 байтам, хотя я использовал функцию _mm_malloc? И при использовании выровненных операций загрузки / сохранения для инструкций SSE я получаю ошибку сегментации, поскольку данные не выровнены по 16 байтам.

Есть идеи, почему он не выровнен должным образом, или какие-либо другие идеи, чтобы исправить это?

Заранее спасибо!


Обновлять

С помощью

printf("%p\n",ptr)

решил проблему с выравниванием памяти, данные действительно правильно выровнены.

Однако я все еще получаю ошибку сегментации при попытке выполнить выровненную загрузку / сохранение этих данных, и я подозреваю, что это проблема с указателем.

При выделении памяти:

contents* instance;
instance.values = (float *) _mm_malloc(h*w*sizeof(float),16);    

У меня есть структура:

typedef struct{
  ...
  float** values;
  ...
}contents;

Затем в коде я выполняю другую функцию с указателем на содержимое, переданным в качестве аргумента:

__m128 tmp = _mm_load_ps(&contents.values);

Вы, ребята, видите что-нибудь, чего мне не хватает? Спасибо за помощь :)


person Ricky    schedule 13.12.2011    source источник
comment
Вы уверены, что h * w * sizeof( float ) делится на 16?   -  person Christopher    schedule 13.12.2011
comment
Я почти уверен, что это так, но h и w переменные. Обязательно ли это число кратное 16?   -  person Ricky    schedule 13.12.2011
comment
Да, конечно. Это загружает 4 поплавка. Таким образом, у вас должно быть как минимум 4 поплавка.   -  person Christopher    schedule 13.12.2011
comment
Я уже обрабатывал это с помощью оператора switch при загрузке переменных, но это не требуется для выделения памяти и не проблема, я думаю, что проблема с указателями, но я не уверен   -  person Ricky    schedule 13.12.2011
comment
Затем вы должны опубликовать сбойный код.   -  person Christopher    schedule 13.12.2011
comment
Похоже, вам нужно изменить _mm_load_ps(&contents.values) на _mm_load_ps(contents.values), поскольку contents.values уже является указателем - та же проблема, что и ваша предыдущая проблема printf - у вас есть тенденция к чрезмерному разыменованию. ;-)   -  person Paul R    schedule 13.12.2011
comment
Пробовал, но получаю error: argument of type "float" is incompatible with parameter of type "const float *"   -  person Ricky    schedule 13.12.2011
comment
Это не соответствует приведенному выше коду - теперь я вижу, что у вас есть значения как float ** - это правильно? Но вы приписываете результат _mm_malloc этому ???   -  person Paul R    schedule 14.12.2011
comment
да это верно. Во время отладки я обнаружил, что ошибку seg вызывает не _mm_load_ps (), а стоящая за ней _mm_store_ps (), которая хранится по тому же адресу &contents.values и дает Access violation reading location 0x00000000.   -  person Ricky    schedule 14.12.2011
comment
Проблема, кажется, сводится к тому, что вы не знаете, что такое указатель против указателя на указатель. содержимое структуры с ее членом значений кажется действительно неправильным. И если вы получаете ошибку чтения в инструкции магазина, должно быть, что-то не так с адресом, который вы передаете.   -  person Christopher    schedule 14.12.2011


Ответы (1)


Изменять:

printf("%p\n", &ptr)

to:

printf("%p\n", ptr)

Выровнять по 16 байт должна именно память, на которую указывает ptr, а не сама фактическая переменная-указатель.

person Paul R    schedule 13.12.2011
comment
Благодаря этому была решена одна часть проблемы, поэтому данные в памяти были правильно выровнены по 16 байт. Но я все еще получаю ошибку сегментации при попытке выполнить согласованную загрузку / сохранение этих данных. Есть ли у этого общие причины? - person Ricky; 13.12.2011
comment
Когда вы получаете ошибку сегментации, вы должны зайти в свой отладчик и посмотреть, какая инструкция вызвала ее и какой был адрес - это должно сказать вам все, что вам нужно знать, чтобы исправить проблему, например невыровненный адрес, недопустимый адрес (вне границ или нулевой) и т. д. - person Paul R; 13.12.2011