为什么使用SSE指令没有提升性能-附代码
最近在做一个程序,中间有一段大量的计算,最核心的一段主要就是乘加操作,原来的C++代码如下:
struct TStatxSimpleRecord
{
float Mean;
float Stdevp;
};
for(i=minx; i<=maxx;i++)
{
float disx2 = square(i*fstepx - x); //squre是自己写的平方函数
for(j=miny; j<maxy; j++)
{
float disy2 = square(j*fstepy - y);
//下面的Exptor.Exp是自己做的快速指数函数,其实就是查表,跟本帖关系不大
float weight = Exptor.Exp((disx2+disy2)*lamda2);
TStatxSimpleRecord * pcd = pxsr[i][j];
//下面代码本来可以用一个循环的,为了提升性能,已经做了循环展开
pcd[0].Mean += weight*gain[0]; //gain和下面的g2都是事先计算得到的一个4个浮点数的数组
pcd[1].Mean += weight*gain[1]; //其中g2[i] = gain[i]*gain[i]
pcd[2].Mean += weight*gain[2];
pcd[3].Mean += weight*gain[3];
pcd[0].Stdevp += weight*g2[0];
pcd[1].Stdevp += weight*g2[1];
pcd[2].Stdevp += weight*g2[2];
pcd[3].Stdevp += weight*g2[3];
}
}
因为上面这两层循环是在一个需要执行200万次的大循环里面,所以对性能影响非常大,现在程序执行一次大约需要12分钟。考虑到上面的数据刚好都是4个浮点数,所以希望通过SSE指令加速一下。下面是用SSE改写的代码:
__asm {
mov eax, t1
movups xmm0, [eax] //复制gain到xmm0
movaps xmm1, xmm0 //复制xmm0到xmm1
mulps xmm1, xmm1 //xmm1平方,得到g2
}
for(i=minx; i<=maxx;i++)
{
float disx2 = square(i*fstepx - x);
for(j=miny; j<maxy; j++)
{
float disy2 = square(j*fstepy - y);
float weight = Exptor.Exp((disx2+disy2)*lamda2);
pdencity[i][j] += weight;
//下面的TVCT是一个临时的结构,struct TVCT{float x; float y; float z; float w;}
//使用这个结构是因为我不知道其他把下面数组内容拷贝到SSE寄存器的方法,
//有人知道的话也请告诉一声,一样有分
TVCT & t2 = *(TVCT *)(pmean[i][j]);
TVCT & t3 = *(TVCT *)(pstd[i][j]);
__asm
{
movss xmm2, weight
shufps xmm2, xmm2, 0x00 //expand weight to 4
mov eax, t2
movaps xmm3, [eax] //mean
movaps xmm4, xmm0 //load gain
mulps xmm4, xmm2 //weight * gain
addps xmm3, xmm4 //mean += weight*gain
movaps [eax], xmm3
mov eax, t3
movaps xmm5, [eax] //std
movaps xmm6, xmm1 //load gain*gain
mulps xmm6, xmm2 //weight*gain*gain
addps xmm5, xmm6
movaps [eax], xmm5
}
}
}
这段代码运行的结果是正确的,与原来的代码得到的结果完全一样(数据16字节对齐的问题我已经注意到了)。但性能出人意料,一点都没有提升(我原来预计有3倍左右的提升),当然也没有降低。
我检查了汇编结果,确实已经使用了SSE指令,寄存器xmm的内容也是正常的。
数据总线的瓶颈我也考虑过,SSE执行的顺序大致安排使得计算跟数据操作分开。
为避免窗口程序的影响,我另外做了一个控制台程序,性能表现没有区别。
现在我想不出还有什7么理由导致性能无法提升,请高手指点。
我使用的CPU:Intel Core Duo T5750,按手册已经CPUID的测试,是支持SSE指令的。
编译器:C++ Builder 2009
OS:Windows Vista Home Basic
struct TStatxSimpleRecord
{
float Mean;
float Stdevp;
};
for(i=minx; i<=maxx;i++)
{
float disx2 = square(i*fstepx - x); //squre是自己写的平方函数
for(j=miny; j<maxy; j++)
{
float disy2 = square(j*fstepy - y);
//下面的Exptor.Exp是自己做的快速指数函数,其实就是查表,跟本帖关系不大
float weight = Exptor.Exp((disx2+disy2)*lamda2);
TStatxSimpleRecord * pcd = pxsr[i][j];
//下面代码本来可以用一个循环的,为了提升性能,已经做了循环展开
pcd[0].Mean += weight*gain[0]; //gain和下面的g2都是事先计算得到的一个4个浮点数的数组
pcd[1].Mean += weight*gain[1]; //其中g2[i] = gain[i]*gain[i]
pcd[2].Mean += weight*gain[2];
pcd[3].Mean += weight*gain[3];
pcd[0].Stdevp += weight*g2[0];
pcd[1].Stdevp += weight*g2[1];
pcd[2].Stdevp += weight*g2[2];
pcd[3].Stdevp += weight*g2[3];
}
}
因为上面这两层循环是在一个需要执行200万次的大循环里面,所以对性能影响非常大,现在程序执行一次大约需要12分钟。考虑到上面的数据刚好都是4个浮点数,所以希望通过SSE指令加速一下。下面是用SSE改写的代码:
__asm {
mov eax, t1
movups xmm0, [eax] //复制gain到xmm0
movaps xmm1, xmm0 //复制xmm0到xmm1
mulps xmm1, xmm1 //xmm1平方,得到g2
}
for(i=minx; i<=maxx;i++)
{
float disx2 = square(i*fstepx - x);
for(j=miny; j<maxy; j++)
{
float disy2 = square(j*fstepy - y);
float weight = Exptor.Exp((disx2+disy2)*lamda2);
pdencity[i][j] += weight;
//下面的TVCT是一个临时的结构,struct TVCT{float x; float y; float z; float w;}
//使用这个结构是因为我不知道其他把下面数组内容拷贝到SSE寄存器的方法,
//有人知道的话也请告诉一声,一样有分
TVCT & t2 = *(TVCT *)(pmean[i][j]);
TVCT & t3 = *(TVCT *)(pstd[i][j]);
__asm
{
movss xmm2, weight
shufps xmm2, xmm2, 0x00 //expand weight to 4
mov eax, t2
movaps xmm3, [eax] //mean
movaps xmm4, xmm0 //load gain
mulps xmm4, xmm2 //weight * gain
addps xmm3, xmm4 //mean += weight*gain
movaps [eax], xmm3
mov eax, t3
movaps xmm5, [eax] //std
movaps xmm6, xmm1 //load gain*gain
mulps xmm6, xmm2 //weight*gain*gain
addps xmm5, xmm6
movaps [eax], xmm5
}
}
}
这段代码运行的结果是正确的,与原来的代码得到的结果完全一样(数据16字节对齐的问题我已经注意到了)。但性能出人意料,一点都没有提升(我原来预计有3倍左右的提升),当然也没有降低。
我检查了汇编结果,确实已经使用了SSE指令,寄存器xmm的内容也是正常的。
数据总线的瓶颈我也考虑过,SSE执行的顺序大致安排使得计算跟数据操作分开。
为避免窗口程序的影响,我另外做了一个控制台程序,性能表现没有区别。
现在我想不出还有什7么理由导致性能无法提升,请高手指点。
我使用的CPU:Intel Core Duo T5750,按手册已经CPUID的测试,是支持SSE指令的。
编译器:C++ Builder 2009
OS:Windows Vista Home Basic
...全文
相关推荐
SSE指令集SSE优化手册
在音频处理中,SSE可用于快速的傅里叶变换(FFT),实现高效的声音编码和解码。总的来说,理解和熟练运用SSE指令集对于优化高性能计算、多媒体处理以及游戏开发等领域的代码至关重要。
SSE指令集:多媒体与科学计算的性能提升
SSE指令集,即Streaming SIMD Extensions,是英特尔公司在1999年发布的扩展指令集,旨在提升多媒体处理和数据并行处理的性能。最初作为Pentium III处理器的一部分,SSE为处理整数和单精度浮点数运算提供了优化。随着时间的发展,SSE经历了多次升级,包括SSE2、SSE3、SSSE3、SSE4.1、SSE4.2以及AVX指令集,使得现代处理器在处理复杂科学计算和图形渲染任务时更加高效。在计算机架构中,数据对齐是指数据在内存中存储的地址对齐到特定的边界。
基于SSE指令集的程序设计简介
基于SSE指令集的程序设计简介作者:Alex Farber出处:http://www.codeproject.com/cpp/sseintro.aspSSE技术简介Intel公司的单指令多数据流式扩展(SSE,Streaming SIMD Extensions)技术能够有效增强CPU浮点运算的能力。Visual Studio .NET 2003提供了对SSE指令集的编程支持,从而允许用
SSE指令集加速.docx
它的设计目的是为了提升处理器在多媒体、图形和科学计算领域的性能。
x86 指令集,sse,等
#### 二、SSE指令集详解##### 2.1 SSE概述SSE(Streaming SIMD Extensions)是一种用于提升多媒体和图形处理性能的扩展指令集。


高性能计算
