Пара вещей, которые я здесь вижу неправильно.Во-первых, ваши операторы, которые загружают регистры XMM и сохраняют значения обратно в вашу переменную, неверны.
asm volatile("movups %0,%%xmm0"::"m"(lhs));
asm volatile("movups %0,%%xmm1"::"m"(rhs));
...
asm volatile("movups %%xmm0,%0":"=m"(lhs));
Следует читать
asm volatile("movups %0,%%xmm0"::"m"(*lhs));
asm volatile("movups %0,%%xmm1"::"m"(*rhs));
...
asm volatile("movups %%xmm0,%0":"=m"(*lhs));
Обратите внимание на *.Вы загружали и добавляли значения указателя, а затем сохраняли их во временном хранилище, которое использовалось для передачи аргумента указателя (который, следовательно, забывается без записи в память при возврате вызова функции).
Даже сэти исправления, в общем, это не очень хорошая техника.Я написал свой собственный пример с операторами asm, но он был ошибочным, потому что я забыл учесть невыровненную природу передаваемых параметров. Это становится очень громоздким, если делать с операторами asm, и намного проще и удобочитаемее с помощью встроенных функций.Просто будьте осторожны, чтобы использовать правильные типы данных:
template<typename T>
void simdAdd(T *lhs,T *rhs)
{
switch(sizeof(T))
{
case sizeof(uint8_t):
{
__m128i lh128;
lh128 = _mm_add_epi8( _mm_loadu_si128( (__m128i *)lhs ),
_mm_loadu_si128( (__m128i *)rhs ) );
_mm_storeu_si128( (__m128i *)lhs, lh128 );
}
break;
case sizeof(uint16_t):
{
__m128i lh128;
lh128 = _mm_add_epi16( _mm_loadu_si128( (__m128i *)lhs ),
_mm_loadu_si128( (__m128i *)rhs ) );
_mm_storeu_si128( (__m128i *)lhs, lh128 );
}
break;
case sizeof(float):
{
__m128 lh128;
lh128 = _mm_add_ps( _mm_loadu_ps( (float *)lhs ),
_mm_loadu_ps( (float *)rhs ) );
_mm_storeu_ps( (float *)lhs, lh128 );
}
break;
case sizeof(double):
{
__m128d lh128;
lh128 = _mm_add_pd( _mm_loadu_pd( (double *)lhs ),
_mm_loadu_pd( (double *)rhs ) );
_mm_storeu_pd( (double *)lhs, lh128 );
}
break;
default:
std::cout<<"error"<<std::endl;
break;
}
}
Что-то, о чем нужно знать, это то, что размер ваших типов данных недостаточен, чтобы знать, какой тип данных вы передали.Тот факт, что тип шаблона имеет тот же размер, что и проверяемые базовые типы, не означает, что это тот же тип.Поэтому я заставляю кастинг покрыть это дело в моем примере.Как правило, это может быть небезопасной практикой, если вы не уверены, что эта функция будет когда-либо использоваться только с указанными вами типами.Например, использование целого числа с плавающей точкой приведет к неожиданно неправильному ответу, и компилятор не сможет предупредить вас об этом.