《提高C++性能的编程技巧》—— 第十三章~第十六章

第十三章 编码优化

  1. 缓存:常见的是将循环内可以提前计算的在循环外部计算

  2. 预先计算:如果将字母全部转化为大写(频繁调用),可以先将所有字母对应的大写字母存储下来,然后直接转化即可

  3. 降低灵活性:如IP地址,直接给一个固定长度的字符存储

  4. 80-20法则:较快常用路径的速度,用||或者&&来增加常用路径速度,||就是为真的概率搞得放前面,&&就是为假的概率高放前面

  5. 延迟计算:等变量要用到时在计算,如一变量只if使用,则在在if声明最好还有就是string放的赋值,直接定义最好,不要先声明

  6. 无用计算完成一步对string对象的赋值例:
    Student::Student(char *nm): name(nm){} //这才是速度最快的
    Student::Student(char *nm): {name = nm} //这个慢。因为会先调用string默认构造函数,将nm转化为string

  7. 系统体系结构
    内存访问差别会很大:数据若位于缓存中,则访问只需要耗费一个CPU周期。若位于主存中,则需要消耗8个CPU周期。
    因此,如果一个类中,两个变量经常一起访问,则最好将两个变量放在相邻的位置

  8. 内存管理
    动态分配和释放对内存的代价比较昂贵,从性能角度讲,不需要显式管理的内存所产生的代价要低得多。
    被定义成局部变量的对象存放于堆栈上。如X *x = new X;与X x;后者代价更小

  9. 库和系统调用
    了解库和系统调用才能写出高性能的代码

  10. 编译器优化

总结:编码优化在范围上是局部的买并且不需要对程序的整体设计有深入的理解。

最快的代码是从不执行的代码,按照以下步骤剔除那些代价高昂的计算
a 您打算使用该计算结果吗?
b 您现在需要该结果吗?
c 您是否已经知道结果?

有的时候无法绕开该计算,name可以加快计算速度:
a 该计算是否过于通用
b 一些灵活性隐藏在库的函数调用中。通过实现库调用的自定义版本可以提升速度,
不过这些库调用必须是频繁的,否则无价值

c 尽量减少内存管理调用的数量。因为绝大多数编译器中,这些调用的代价高
d 如果考虑所有可能的输入数据。则可以发现20%的数据在80%的时间里出现。
因此可以牺牲其他不经常出现的场景为代价来提高典型输入的处理速度
e 缓存、RAM和磁盘访问的速度差异明显,应该多编写缓存友好的代码

第十四章 设计优化

总结:

  1. 对于在80%时间内执行的20%软件,性能通常损失在灵活性上
  2. 在代码细节中可以利用缓存优化代码,在整个程序设计中也可以,通常可以将先前的计算结果保存起来避免大量的计算
  3. 对于软件的高效性而言,使用高效的算法和数据结构是必要条件
  4. 有些计算只有在特定条件下才需要。这些计算应该被推迟到确实需要它们的路径上来完成。过早的计算可能被未被使用
  5. 大型软件往往会变得错综复杂,混乱软件的一大特点就是执行失效代码。定期清理失效和僵死代码可以增强软件性能

第十五章 可扩展性

  1. SMP(对称多处理器架构)是当前主流的多处理器架构,他通过一条总线连接多个对称的处理器和一个内存系统。
    总线是SMP架构可扩展性的薄弱环节,让每个处理器都有自己的大缓存可以有效的控制总线的竞争

  2. Amdahl(顺序的任务中有些不可以并行化)定律给出了一个应用的可扩展性上限,顺序化计算限制了扩展性

  3. 实现可扩展性的技巧是减少或者消除顺序化代码。一下是达到这个目标的一些步骤:
    任务分解:将大的任务分为小任务,使线程并发的执行这些小任务
    代码移出:临界区应该只包含关键代码,不直接操作共享资源的代码不要放在临界区内
    利用缓存:有事,通过缓存之前访问过的数据,可以消除对临界区的访问
    无共享:如果需要少量、数目固定的资源实例,可以不使用公共资源池。可以将这些资源实例设为线程私有,并最后回收
    部分共享:有两个一样的资源池可以减少一半的竞争
    锁粒度:不要用同样的锁来保护所有的资源,除非这些资源是同时更新的
    伪共享:不要在类定义里吧两个使用频度都很高的锁放太靠近,因为可以出现他们共享同一个缓存行并触发缓存一致性风暴
    惊群现象:仔细分析您的锁调用的特征。当锁被释放时,是所有的等待线程都被唤醒还是只唤醒一个,唤醒所有线程会威胁到应用的可扩展性
    系统和类库调用:考察这些调用的实现特征。他们有可能是隐藏了顺序化的代码
    读/写锁:以读为主的共享数据会从这种锁中获益,使用这种锁,可以消除读者线程之间的竞争

第十六章 系统体系结构相关话题

  1. 要使用的存储器离处理器越远,访问的所需时间就越长。离处理器最近的是寄存器,虽然容量很少,但是速度很快。
    对寄存器的优化对象程序的性能提升而言是极为有益的

  2. 虚拟存储器并不是无偿的,不加选择的依赖系统管理的虚拟结构可能会影响性能,而且一般都是降低性能

  3. 上下文的开销巨大,请避免上下文切换(线程切换)

  4. 虽然内部管理异步IO有它的重要作用,我们还是认为正在到来的处理及架构的变化,会使得单个线程方法在方面的优势减弱

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容