use*_*526 1 c++ gcc inline-assembly sse2
我有这个函数使用SSE2将一些值加在一起它应该将lhs和rhs加在一起并将结果存储回lhs:
template<typename T>
void simdAdd(T *lhs,T *rhs)
{
asm volatile("movups %0,%%xmm0"::"m"(lhs));
asm volatile("movups %0,%%xmm1"::"m"(rhs));
switch(sizeof(T))
{
case sizeof(uint8_t):
asm volatile("paddb %%xmm0,%%xmm1":);
break;
case sizeof(uint16_t):
asm volatile("paddw %%xmm0,%%xmm1":);
break;
case sizeof(float):
asm volatile("addps %%xmm0,%%xmm1":);
break;
case sizeof(double):
asm volatile("addpd %%xmm0,%%xmm1":);
break;
default:
std::cout<<"error"<<std::endl;
break;
}
asm volatile("movups %%xmm0,%0":"=m"(lhs));
}
Run Code Online (Sandbox Code Playgroud)
我的代码使用这样的函数:
float *values=new float[4];
float *values2=new float[4];
values[0]=1.0f;
values[1]=2.0f;
values[2]=3.0f;
values[3]=4.0f;
values2[0]=1.0f;
values2[1]=2.0f;
values2[2]=3.0f;
values2[3]=4.0f;
simdAdd(values,values2);
for(uint32_t count=0;count<4;count++) std::cout<<values[count]<<std::endl;
Run Code Online (Sandbox Code Playgroud)
但是这不起作用,因为当代码运行时,输出1,2,3,4而不是2,4,6,8
我发现内联汇编支持在大多数现代编译器中都不可靠(例如,实现只是简单的错误).通常最好使用编译器内在函数,它是看起来像C函数的声明,但实际上编译为特定的操作码.
Intrinsics允许您指定操作码的确切序列,但将寄存器着色留给编译器.它比在C变量和asm寄存器之间移动数据更可靠,这是内联汇编程序总是让我失望的地方.它还允许编译器安排您的指令,如果它可以解决管道危险,则可以提供更好的性能.即,在这种情况下你可以做到
void simdAdd(float *lhs,float *rhs)
{
_mm_storeu_ps( lhs, _mm_add_ps(_mm_loadu_ps( lhs ), _mm_loadu_ps( rhs )) );
}
Run Code Online (Sandbox Code Playgroud)
无论如何,在你的情况下,你有两个问题:
*lhs
和*rhs
,而不是仅仅LHS和RHS; 显然,"= m"语法意味着"隐式使用指向我正在传递给你的东西的指针而不是东西本身."xmm1
,而不是xmm0
.我在键盘上放了一个固定的例子(以避免弄乱这个答案,并证明它有效).
归档时间: |
|
查看次数: |
2364 次 |
最近记录: |