首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

为什么VC的内联汇编函数性能不如C++函数解决办法

2012-03-02 
为什么VC的内联汇编函数性能不如C++函数小弟最近编一段程序,性能要求比较高,花了两天功夫,将C++函数改写成

为什么VC的内联汇编函数性能不如C++函数
小弟最近编一段程序,性能要求比较高,花了两天功夫,将C++函数改写成汇编函数,结果发现汇编函数的性能俱然不如C++函数,狂郁闷。
下面将代码贴出,各路高手帮我测试一下。

//------------------------begin-----------------


//使用到的一些结构

//直线
typedef   struct   LINEtag
{
floata;
floatb;
floatc;
floatd;
}LINE;

//顶点
typedef   struct   XPOINT32Ftag
{
floatx;
floaty;
  }POINT32F,*PPOINT32F;

//多边形
typedef   struct   XRGN32Ftag   XRgn32F;
struct   XRGN32Ftag
{
POINT32F   *v;
intiV;
floatx;     //原点X
floaty;     //原点Y
floatw;     //多边形外接矩形宽度
floath;     //多边形外接矩形高度
XRgn32F   *next   ;
LINE*line   ;   //多边形边的直线
}     ;

//该函数求组成多边形的每一条边的直线,该函数使用汇编代码编写,对3280个顶点
//测试,使用时间为5004纳秒
//POINT32F   *pPos   [IN]   存放组成多边形的各点
//LINE   *lines         [OUT]   输出每条边的直线
//int   nPos               [IN]   多边形的顶点数,也就是pPos数组的维数
inline   void   cxMakeLines32F_asm(POINT32F   *pPos,   LINE   *lines,int   nPos)
{

_asm
{

mov   ebx,0;
mov   ecx,nPos;
mov   esi,dword   ptr   [pPos]   ;
mov   edi,dword   ptr   [lines]   ;

//{:   Begin   Loop   0     ----i=0

mov   eax,ecx;
sub   eax,1;
imul   eax,8;

fninit;
fld   [esi+eax]   ;
fld   [esi+eax+4]   ;
fld   [esi]   ;
fld   [esi+4]   ;
fld   st(0)   ;//取出y2
fsub   st(0),st(3)   ;//y2-y1
fldz   ;//将0压栈
fucomp   st(1)   ;//tl.a <0
jnge   _mlnext;//如果小于0,就跳转_mlnext0

fchs;//-1*tl.a
fstp   dword   ptr   [edi];//保存结果   a
fld   st(3)   ;//将x1压栈
fsub   st(0),st(2);//x1-x2
fchs;//-1*tl.b
fstp   dword   ptr   [edi+4];//保存结果   b
fld   st(3)   ;//将x1压栈
fmul   st(0),st(1)   ;//x1*y2
fstp   st(5);//将st0数据放到st5,并将st0弹出栈
fld   st(2)   ;//将y1压栈
fmul   st(0),st(2)   ;//y1*x2
fsub   st(0),st(5)   ;//y1*x2-x1*y2
fchs;//-1*tl.c
fstp   dword   ptr   [edi+8];//保存结果   c
jmp   _mlout   ;//跳转到_mlout
_mlnext:
fstp   dword   ptr   [edi];//保存结果
fld   st(3)   ;//将x1压栈
fsub   st(0),st(2);//x1-x2
fstp   dword   ptr   [edi+4];//保存结果
fld   st(3)   ;//将y1压栈
fmul   st(0),st(1)   ;//x1*y2
fstp   st(5);//将st0数据放到st5,并将st0弹出栈
fld   st(2)   ;//将y1压栈
fmul   st(0),st(2)   ;//y1*x2
fsub   st(0),st(5)   ;//y1*x2-x1*y2
fstp   dword   ptr   [edi+8];//保存结果  
_mlout:

//:}   End   Loop   0

dec   ecx;
add   edi,16;

//{:   Begin   Loop     ---   i   =   0   to   nPos
_beginloop:

//{:   Begin   make   line
_beginmakeline:

fninit;
fld   [esi]   ;
fld   [esi+4]   ;
fld   [esi+8]   ;


fld   [esi+12]   ;
fld   st(0)   ;//取出y2
fsub   st(0),st(3)   ;//y2-y1

fldz   ;//将0压栈
fucomp   st(1)   ;//tl.a <0
jnge   _makelinenext;//如果小于0,就跳转_mlnext0

fchs;//-1*tl.a
fstp   dword   ptr   [edi];//保存结果   a
fld   st(3)   ;//将x1压栈
fsub   st(0),st(2);//x1-x2
fchs;//-1*tl.b
fstp   dword   ptr   [edi+4];//保存结果   b
fld   st(3)   ;//将x1压栈
fmul   st(0),st(1)   ;//x1*y2
fstp   st(5);//将st0数据放到st5,并将st0弹出栈
fld   st(2)   ;//将y1压栈
fmul   st(0),st(2)   ;//y1*x2
fsub   st(0),st(5)   ;//y1*x2-x1*y2
fchs;//-1*tl.c
fstp   dword   ptr   [edi+8];//保存结果   c
jmp   _endmakeline   ;//跳转到_mlout

_makelinenext:
fstp   dword   ptr   [edi];//保存结果
fld   st(3)   ;//将x1压栈
fsub   st(0),st(2);//x1-x2
fstp   dword   ptr   [edi+4];//保存结果
fld   st(3)   ;//将y1压栈
fmul   st(0),st(1)   ;//x1*y2
fstp   st(5);//将st0数据放到st5,并将st0弹出栈
fld   st(2)   ;//将y1压栈
fmul   st(0),st(2)   ;//y1*x2
fsub   st(0),st(5)   ;//y1*x2-x1*y2
fstp   dword   ptr   [edi+8];//保存结果  

_endmakeline:
//:}   End   make   line

add   esi,8;
add   edi,16;
inc   ebx;

cmp   ebx,ecx;
jnge   _beginloop   ;

_endloop:
//:}   End   Loop


}


}


//   根据已知两点坐标,求过这两点的直线解析方程:   a*x+b*y+c   =   0     (a   > =   0)    
LINE   makeline(float   x1,float   y1,float   x2,float   y2)  
{  
LINE   tl;  
int   sign   =   1;  
tl.a=y2-y1;  
if(tl.a <0)  
{  
sign   =   -1;  
tl.a=sign*tl.a;  
}  
tl.b=sign*(x1-x2);  
tl.c=sign*(y1*x2-x1*y2);  
return   tl;  
}  

//该函数求组成多边形的每一条边的直线,使用该函数对3280个顶点
//测试,使用时间为3128纳秒
//POINT32F   *pPos   [IN]   存放组成多边形的各点
//LINE   *lines         [OUT]   输出每条边的直线
//int   nPos               [IN]   多边形的顶点数,也就是pPos数组的维数
void   cxMakeLines32F(POINT32F   *pPos,   LINE   *lines,int   nPos)
{

int   i0   =   nPos-1   ;
int   i   =0   ;
lines[i]   =   makeline(pPos[i0].x,pPos[i0].y,pPos[i].x,pPos[i].y);
for   (   i   =   1   ;   i   <   nPos;   i++   )
{
i0   =   i-1;
lines[i]   =   makeline(pPos[i0].x,pPos[i0].y,pPos[i].x,pPos[i].y);
}

}

//从文本文件当中读取多边形
//char   *file   [IN]   文本文件名称
//文件格式:x   y
//218.90   319.20
//321.81   234.09
//......略
XRgn32F   readRgn(char   *file)
{
ifstream   inf(file);
POINT32F   *ps0   =   new   POINT32F[5000];
POINT32F   *ps1   =   ps0   ;
int   np   =   0   ;
float   right,bottom;



right   =   bottom   =   0   ;

while(   !inf.eof()   )
{
inf> > ps1-> x> > ps1-> y   ;
np++;
if   (   right   <   ps1-> x   )     right   =   ps1-> x   ;
if   (   bottom   <   ps1-> y   )   bottom   =   ps1-> y   ;

ps1++;
}

XRgn32F   rgn;
rgn.v   =   ps0;
rgn.iV   =   np-1;
rgn.x   =   rgn.y   =   0;  
rgn.w   =   right;
rgn.h   =   bottom;

return   rgn   ;

}

//测试性能的代码
void   Test()
{

                  //读取多边形
XRgn32F   rgn   =   readRgn( "F:\\Bin\\pos2.txt ");
rgn.line   =   new   LINE[5000];

LARGE_INTEGER   litmp;
double   dCountsNow,dCountsNext,dCountsDif;
//超精确时间函数
//取当前CPU时钟计数器计数
QueryPerformanceCounter(&litmp);
dCountsNow=(double)litmp.QuadPart;

//cxMakeLines32F(   rgn.v,rgn.line,rgn.iV   )   ;         //使用C++函数计算
cxMakeLines32F_asm(   rgn.v,rgn.line,rgn.iV   )   ;     //使用汇编函数计算

QueryPerformanceCounter(&litmp);
dCountsNext=(double)litmp.QuadPart;
dCountsDif   =   dCountsNext-dCountsNow   ;                     //计算使用时间


}



[解决办法]
内联汇编调用C/C++函数必须自己清除堆栈
[解决办法]
哎还是别手工优化了,用编译器的优化功能吧
[解决办法]
要分析一下代码消耗的时间主要在什么部分 .....

如果是在外部数据读取上,
那么用汇编能提高什么啊 ~
[解决办法]
这种不使用CPU特别的指令的东东手工汇编应该很难超过编译器优化吧, 偶觉得你这样照着翻译的汇编代码超过机器优化应该很难, 还是考虑考虑SSE啥的可能有点希望 ...
[解决办法]
非专业人士,很难写出比编译器最优化后更快的代码,不值得太浪费时间。
[解决办法]
差了一个数量级啊

热点排行