以文本方式查看主题

-  计算机科学论坛  (http://bbs.xml.org.cn/index.asp)
--  『 C/C++编程思想 』  (http://bbs.xml.org.cn/list.asp?boardid=61)
----  加快程序运行速度的技巧[转]  (http://bbs.xml.org.cn/dispbbs.asp?boardid=61&rootid=&id=38406)


--  作者:zhu_ruixian
--  发布时间:9/28/2006 1:43:00 PM

--  加快程序运行速度的技巧[转]
通常影响程序运行速度的地方,都是在执行次数最多的地方。比如显示一张800*600的256色图形,如果在设置调色板时浪费了0.001秒,那么对整个程序不会有很大影响,因为设置调色板的操作只要作一次就完成,但是每绘出一点要多浪费0.001秒,那么整张图画完就会慢上800*600*0.001秒,这是一个相当可观的数目。下面介绍一些常用的技巧。

一.尽量使用整数,少用浮点数
  整数运算比浮点数快得多,而在绘图程序中用到小数点的机会实在少之又少,所以这是很容易做到的技巧。

二.避免乘法与除法
  乘法与除法都是相当浪费CPU运算时间的一种运算,所以在绘图程序中应尽量避免,在无法避免时,如果乘除的数目为2次方,例如2、4、8、16等,则可改用左移或右移来取代:

a*2^n-->a<<n 例:a*16-->a<<4
a/2^n-->a>>n 例:a/32-->a>>5

  上式中2^n表示2的n次方。

三.少用求模运算
  求模的运算(%)通常也是用乘除来完成的,所以速度很慢,我们也要尽量避免,当然如果除数为2的次方,那么可以改用&来替代:

a%2^n --> a&(2^n-1)

例:a%8 --> a&0x07

注意,如果除数不是2的次方,绝不能用&来替代。

四.复杂的二维计算改用查表法
  所谓查表法,就是事先将一些运算结果存入表格中,然后在需要时直接取出来使用而不必再做运算。最常见的例子就是在做图形旋转时,往往会用到sin()、cos()等函数来计算角度,如果能将这些运算结果事先存于表格中,那么必能省下相当多的时间。
  对于较简单的显示图形的程序,我们也可以利用查表法来避免乘法的使用。例如在320*200*256模式下,我们要在(x,y)的地方画出一点,那么必然要做(y*320+x)的计算,如果能将每一条起始扫描线的位置事先算出并存入表格中:

unsinged table[200];
for( i=0; i<200; i++ )
    table[i] = i * 320;

那么在绘点时便可以直接使用下面的方法来取得位置:

table[y] + x;

避免了乘法运算,这就是“以空间换取时间“的做法。还有一种变形的查表法也值得一提,那就是如果在程序中有很多地方都用到了相同的运算,那么可以事先算出结果并加以储存,例如:

......
MaxSize = width * height * 3 + 200;
......
MinSize = width * height * 3 - 100;
......

则可先算出size:

size = width * height * 3;
......
MaxSize = size + 200;
......
MinSize = size - 100;
......

五.将耗时的运算移到循环之外
  通常在循环内的程序码会执行较多次,所以应减少耗时的运算,例如320*200*256模式政绘制一个实心的矩形时:

char far *vp = (char far *)0xA0000000L;
for( y=50; y<150; y++ )
    for( x=100; x<200; x++ )
        *(vp+y*320+x) = 0x0f;

可以改成:

char far *vp = (char far *)0xA0000000L;
char far *p;
for( y=50; y<150; y++ )
{
    p = vp+y*320+100;  /* 将乘法移出内层循环*/
    for( x=100; x<200; x++ )
        *(p++) = 0x0f;
}

再进一步还可以更上一层楼,将乘法完全移出循环:

char far *vp = (char far *)0xA0000000L;
char far *p;
int offset = 320-(200-100);
p = vp+50*320+100;
for( y=50; y<150; y++ )
{
    for( x=100; x<200; x++ )
        *(p++) = 0x0f;
    p += offset;
}

其中offset的值正是矩形中最右边的一点到下一条扫描线最左边一点的差距值。

六.使用寄存器变量
  寄存器的存取速度要比内存快,一般c/c++编译器都至少提供1~2个寄存器变量给程序使用,我们应该将使用最频繁的变量定义成寄存器变量,这样可以加快执行效率,例如:

register int i;
for( i=0; i<3000; i++ )
    *(p+i) = 0x0f;

七.编译器的设置
  在编译程序时,我们也可以通过某些设置来加快程序效率,例如,产生最快的执行速度的最佳化,不做堆栈溢出检查等,如果你使用tc20,那么只要在Option菜单中选Compiler/Optimizations,然后选择底部的Fastest Code按钮便可。读者可以自行参考相关手册。


--  作者:Krise77
--  发布时间:10/2/2006 7:13:00 PM

--  
懂了,谢谢!
W 3 C h i n a ( since 2003 ) 旗 下 站 点
苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
46.875ms