提高c++性能的一些建议

来源:互联网 发布:淘宝在线人数免费插件 编辑:程序博客网 时间:2024/06/11 00:02

下面的内容是对国外一前辈agner关于cpp软件优化文档的一个整理,相当于学习笔记,放在这里,跟大家分享一下。

来自《optimization_cpp.pdf》

 

 转载请注明出处:http://blog.csdn.net/qingheuestc

Edited by Einstein in 2011年11月3日 afternoon

 

1,操作系统对硬盘文件一般会进行缓存,但对usb或者floppy disk则不一定。优化file operation时考虑cache、数据的存储方式(二进制还是assic)。

 

2,Windows系统下,不要用系统提供的数据库。读写文件的方式比读写数据库快多了。如果实在要用数据库,要熟悉数据库的各种调优方法。

3,很多需要进行系统调用的地方,如果可以用collective和cache思想,尽量使用,这样可以减少ring0和ring3之间切换带来的开销。

 

4,上下文的切换带来的开销是非常可观的,data cache,instructioncache,branch target buffer, branch pattern history ,etc may have to be renewed!

5,避免长的dependency chain,不然 乱序执行的优点则荡然无存。另外,为了充分利用execution unit,考虑适当的搭配不同指令(比如不同计算部件的指令放在一起,而不是同一种计算放在一起)

 

6,程序运行缓慢的几大元凶:

a) 运行时框架,such as.NET,jvm等。

b) 内存交换。对数据的利用不够充分,或者说局部性利用的不够好。

7,选择高效的算法。对于排序,查找,数学运算等,算法的选取至关重要。如果一个简单的算法足够高效,不要去选取一个复杂的算法。另外,在开始编码前,先调查看看有没有别人做过类似的东西。避免重复工作。

 

8,如果没有大的数组,则栈中的局部数据很可能被存在L1cache中。因此,所有的变量和对象应该在他们被使用的地方定义(其实仅从语义的角度考虑,也是要将局部数据定义在局部)。为了提高变量的局部性,可以尝试用加{}的方法,尽管有的编译器只有在函数返回的时候才释放变量的内存。如果一个变量被存储在寄存器中,那么他会在函数返回前被释放掉。

 

9,Static变量可以被用在浮点常量,字符串常量,数组初始化列表,switch的跳转表中,虚函数表中等。一般分为三部分:

a) 永远不会被程序改变的

b) 已经被初始化,并有可能被程序修改的。

c) 为被初始化,并有可能被程序修改的。

 

10,全局和静态变量有可能会降低cache的效率,但是他们的优点是记录状态信息。

 

11,程序中被初始化的静态变量直接被存放在固定的位置,另外,相同的字面值常量(浮点和字符串)会被视为一个以节约内存(他们很可能放在不可被改变的static区域)。整数常量一般会被编码到指令中去,因此完全不用考虑整型常量的cache问题。

 

12,整数寄存器32位有6个,64位有14个(x86),浮点寄存器32位有8个,64位有16个。打开SSE2指令支持,可以让一些编译器充分利用floatpoint寄存器。

 

13,Volatile指明一个变量不能被存放在register中。多个线程都会访问的地址有必要用volatile来修饰。另外,有时也被用来修饰某些变量以防止编译器对其进行优化。

 

14,避免使用thread-localstorage,有些编译器支持通过__thread 或者__declspec(thread)来使用静态或全局变量,但应注意,他们是通过线程环境块里的指针来访问这些变量的,所以速度并不快。

 

15,避免使用far(使用far可以用来访问不同data segment或者code segment的内容,但效率极低。可以选用更大段的操作系统。

 

16,动态内存分配是相当低效的。它不仅保存了一些对程序而言无用的标识块,而且有最小尺寸限制(比如在64位平台上,最低的块大小是32byte),另外还会因为不合适的malloc和free顺序等因素产生很多碎片,导致其cache利用率极低。这还不包括各种管理的开销。一些语言比如java,所有的对象都使用dynamic memoryallocation,效率当然低下。

17,变量是按照在类中的声明的顺序进行存储的,存储的类型在类声明的地方确定。对象不会被存储在register中,除非是最简单的对象。但是他的数据成员可以被放在register里。

 

18,对于整型变量和操作,考虑

a)  使用头文件来消除不同平台上类型尺寸带来的问题

b)  如果变量的大小无关紧要而且也不会发生溢出(中间结果溢出也要考虑在内),尽量使用标准长度的整型。

c)  无符号和有符号变量的计算速度基本差不多,除了下面的情况

                 i. 当被常量除的时候或者做%运算时,无符号快于有符号

                 ii. 当被转换为浮点数时,有符号快于无符号。

                iii. 避免有符号和无符号数的任何形式的计算(尽量避免不同类型数据之间的计算)。

                iv. 在大部分的处理器上,整数之间大部分的计算都可以在一个cycle完成,mul运算3-4cycle(pentium上11cycle),div运算40-80cycle。

                v.  i++和++i的速度一样,但用在a[i++]或者a[++i]则不同了。后者有个数据依赖,大约要慢一个cycle。在另外一些情况下,比如a=++b和a=b++,此时前者可能优于后者因为在编译器优化时,a和b可以被优化到一个register中去。

原创粉丝点击