добавление двух 4-векторов с sse с помощью указателей

Этот кусок кода (удваивающий 4-вектор) работает:

__declspec(align(16)) struct vec4 { float a[4]; };

int main()
{
vec4 c;
c.a[0]=2;
c.a[1]=0;
c.a[2]=0;
c.a[3]=0;

__asm {
movaps xmm1, c

addps xmm1, xmm1
movaps c, xmm1
}
}

Но этот фрагмент (делает то же самое, но теперь с указателем на выровненные данные):

__declspec(align(16)) struct vec4 { float a[4]; };

int main()
{
vec4* c = new vec4;
c->a[0]=2;
c->a[1]=0;
c->a[2]=0;
c->a[3]=0;

__asm {
movaps xmm1, c

addps xmm1, xmm1
movaps c, xmm1
}
}

Зачем?

Мне нужно, чтобы он работал с указателями, потому что я не могу использовать сами выровненные данные в качестве аргумента функции.

2

Решение

Указатель в ASM должен обрабатываться в соответствии с определенными правилами, которые вы можете узнать в значительной степени, изучив как работает «MOV».

По правилам Ассемблера, сначала нужно скопировать указатель в регистр процессора. тогда вы можете использовать его, чтобы указать на ячейку памяти.

vec4 *d = ...;
__asm {
mov eax, d
movaps xmm1, [eax]

addps xmm1, xmm1
movaps [eax], xmm1
}
0

Другие решения

Проблема в том, что объекты, созданные распределителем кучи (например, new и malloc), не следуют указанному выравниванию. Вы получаете выравнивание только с выделенным стеком объектом (ваш первый пример).

C ++ 11 поддерживает явное выравнивание объектов, выделенных через кучу с помощью alignas, но это пока не реализовано в VC ++. Это будет работать с некоторыми компиляторами, а не с другими.

У вас есть несколько вариантов.

Самый простой: создайте выделенный объект кучи, как вы это сделали, и скопируйте его в выделенный объект стека, прежде чем использовать его:

vec4* c = new vec4;
c->a[0]=2;
c->a[1]=0;
c->a[2]=0;
c->a[3]=0;

vec4 d = *c;
// process with d

Другой вариант заключается в том, чтобы ваша структура vec4 включала достаточно дополнительной памяти, чтобы вы гарантированно имели 16 байтов при 16-байтовом выравнивании. Я считаю, что новый гарантирует как минимум 4 байта выравнивания, поэтому 28 байтов сделали бы это. Затем вам нужно будет вручную проверить указатель, чтобы увидеть, где вы хотите хранить данные, которые будут использоваться с sse.

0

По вопросам рекламы [email protected]