编译器比你聪明


#1

程序员总是倾向于编写所谓的 “优化” 代码, 认为他们这样写的代码要执行的更快. 并且他们甚至以 “效率” 为借口编写大量的可读性非常糟糕的代码. 很可惜的是, 事实上他们所谓的 “高效” 的代码很可能并不高效, 甚至适得其反, 效率非常低下.

警告, 本讲座包含高级内容, 慎入


引言

  • 优化很重要
  • 可读性更重要
  • 那就了解你的编译器, 编写可读性的代码, 让编译器去做优化

目标读者

先问问自己

  • 有多少人知道CPU流水线?
  • 你对乱序执行知道多少?
  • 什么是寄存器重命名

本讲座的主要目的是说服那些经常手写汇编代码, 并且认为低级语言=高效的人 .


[系列教程] 通往现代c++之路之1 --- 你要摒弃的几个 c++ 陋习
#2

一直小心翼翼的编写逻辑清晰的代码。


#3

贯彻执行 除非是做非常底层的工作 直接涉及编译结构的


#4

通常我喜欢 先是可读性 逻辑注释多的代码. 待N轮儿测试过后, 再慢慢地改成可读性灰常糟糕的代码.(当然, 大部分没有这个时间去弄这些).


#5

通常都是说先把功能哼唧哼唧实现,然后优化。但是从来没到优化,就转下个功能了。


#6

有些人,整天都在纠结i++/++i,for/while之间效率,这些人认为自己比编译器聪明,这种落后的观念,直到今天,依然大有人在。。。


#7

呃… 就是啊. 当年的那啥学校教育, 都在纠着 ++i i++ 这些考来考去. 有嘛意思…


#8

流水线 乱序 -> 这不是体系结构课本里面的基础知识么


#9

说的真好,记得上一年考c++的时候,老师就是这样考,当时我跟小伙伴们都惊呆了。


#10

有这个经验,等待开课……

xoxo 油菜


#11

期待ing 编译器不能优化你的代码,肯定是因为你没有告诉编译器你的意图(void*)


#12

我觉着最好全面铺开讲解关键是什么时候需要汇编优化 什么时候不需要汇编优化 比如 很多时候我们需要特殊的指令集 或者有单独高效的浮点运算器 是需要的汇编层次优化的


#13

使用常变量代替宏定义

#define CONSTANT 23
const int constant = 23;
enum { constant = 23  };

这样的代码, 我们当然觉得常变量定义要比宏好, 因为对调试更友好. 你能直接查看变量, 并且你使用常量的时候编译器能进行 类型检查 , 有利于你及早的发现错误.

当然, 有人会说, 用宏的话可以避免一次变量引用, 能生产更高效的代码.

事实真是如此么???

enum { constant=23 };
#define CONSTANT 23
static const int Constant=23;
void foo(void) {
a(constant+3);
a(CONSTANT+4);
a(Constant+5);
}

我们希望编译器对这三次函数调用生成一样的代码, 都直接使用一个常量作为参数而无需生成变量访问.

fooo 的汇编

sub $8, %rsp
mol $26,%edi
call a
movl %27, %edi
call a
movl $28, %edi
add $8,%rsp
jmp a

可以看到, 编译器在调用 a 的时候, 都使用了常量, 而没有生成对变量的访问.


#14

#define VS 只读变量

对编译器来说, 能优化到不存取这样的变量, 所以没有任何效率损失. 使用只读变量, 能带来可读性的提升, 并且还能利用上编译器的类型检查


#15

加上错误信息会更加明确,因为它进入了符号表。


#16

果断是const好,个人认为。


#17

上面汇编不是说了么,没有生成对变量的访问。


#18

#19

#20

yeah,总有一些人,不看事实,代码里到处充满了void*,还认为qsort比c++模板sort高效呢,比如云风。