准备写一个系列,驳斥一下这些年我整理/设计的高性能编码规范里,哪些是没有意义的。为什么会没有意义呢?有的原因可能是规则本身是有问题的,有的原因可能是编译器会帮我们优化,有的可能存在局限性,还有可能有些其他原因。

第一个规则:

如果循环体内存在逻辑判断,宜将逻辑判断移到循环体的外面。

这是部门社招主观题的一个考点,也是一本老书《大话处理器》里关于代码优化的章节开头的例子。形如下述代码:

for(i = 0; i < N; i++)
{if(A)DoSomething();elseDoOthers();
}

一般认为是低效的,因为循环内做了条件判断,推荐代码形如:

if(A)
{for(i = 0; i < N; i++)DoSomething();
}
else
{for(i = 0; i < N; i++)DoOthers();
}

理论分析下:

1.如果A是常量/宏,编译器应能优化掉另一个分支;

2.如果A是变量,处理器应有分支预测功能,特别是现在一些强大的芯片,用于预测的空间应该是很大的。也就是说,对于变化较少的变量,依赖芯片的分支预测功能,这个规则是没有意义的。

3.如果A是经常变化的变量,处理器应不会进行预测,在这个场景下,这个规则应该是有意义的。

4.再从设计上分析下,方式二有循环语句重复,应该是要尽量避免的。

针对1,设计代码如下:

低效代码low.c:

#include <stdio.h>
#include <time.h>
int a = 1;
int sum = 0;
#define N 1000000
int main()
{clock_t start, end;start = clock();for(int i = 0; i < N; i++){if(a)sum += i;elsesum = sum + 2 * i ;}end = clock();printf("%ld", end - start);
}

高效代码high.c:

#include <stdio.h>
#include <time.h>
int a = 1;
int sum = 0;
#define N 1000000
int main()
{clock_t start, end;start = clock();if(a)for(int i = 0; i < N; i++)sum += i;elsefor(int i = 0; i < N; i++)sum = sum + 2 * i ;end = clock();printf("%ld", end - start);
}

结果如下:

从这个实验结果里能得出的结论如下:

  1. 低效写法在大部分情况下效率确实低;
  2. 在这个典型写法下,10亿次与100万次循环,low和high的差距比例变化不大,均在30%左右;
  3. a=0,即分支预测失败时,low变化不大,high性能恶化24%,low high差距缩小为5%。
  4. (O2与O1差不多)O1优化下,差距比例扩大为50%;
  5. 用const声明变量a,O0下二者几乎一样。存疑。
  6. O3优化二者几乎一样;存疑。

根据3,应有如下编码建议:

执行概率高的分支应放在概率低的分支前面。

对于疑问5,取gcc -O0 -fverbose-asm -S low.c,查看汇编发现,相比于非const,const仅仅是把a替换成了1,能把low代码性能提升30%!从汇编上似乎解释不了,推测应该是流水带来的收益。应有如下编码建议:

对于版本确定无疑的开关,应使用const或者宏,不应使用普通变量。

对于疑问6,查看汇编发现,low代码结构已优化成与high的基本相同,即在循环外层进行条件判断。还是存疑,有没有可能O3通过分析代码,明确按照a=1的分支编译。进一步,将a改为0,发现汇编代码顺序没有发生变化,开销均变为a=1的2倍。所以应有如下结论:

文章开头提到的编码规范在O3下没有意义。

如果条件a与循环下标i有关系,没法优化,不在本文讨论的范围内。

本文通过几组实验,说明了下面几个有意义的结论:

  1. 文章开头提到的编码规范在O3下没有意义,考虑到循环语句重复,我认为不应再坚持这个编码规范;
  2. 执行概率高的分支应放在概率低的分支前面;
  3. 对于版本确定无疑的开关,应使用const或者宏,不应使用普通变量。

查看分支编码_高性能编码规范驳斥(一)相关推荐

  1. 遗传算法编码方式整数编码_如何编码卫星算法并从头开始烹制西班牙海鲜饭

    遗传算法编码方式整数编码 What if I told you that by the end of this article, you'd be able to calculate the orbi ...

  2. 深度学习去燥学习编码_学习编码的警示故事。 我自己的。

    深度学习去燥学习编码 I was just a guy in a suit in an office with a vague startup idea. Then I decided to lear ...

  3. 如何查看笔记本的语言编码_在编码笔记本电脑中寻找什么

    如何查看笔记本的语言编码 Did you just graduate from your coding bootcamp and now have to return your loaner lapt ...

  4. 未来视频编码_设计编码营销并消费未来

    未来视频编码 数字化转型的伦理 (The Ethics of Digital Transformation) Are you a human, and do you own a smartphone, ...

  5. 算法训练营 重编码_完成编码训练营后的第一年,我学到了教训。

    算法训练营 重编码 by Mario Hoyos 通过马里奥·霍约斯(Mario Hoyos) 完成编码训练营后的第一年,我学到了教训. (Lessons I learned the first ye ...

  6. 视觉中国图片编码_学习编码第14天的应用视觉设计第4部分

    视觉中国图片编码 Goooood evening everyone! Yesterday was a short little blog as we came to the end of the se ...

  7. 解决文件内容的中文乱码_字符集_字符编码_字符编码方案

    从第三方下载的java源文件,打开查看里面的中文全部是乱码,无论你使用什么字符编码集都无法正常显示,该文件是用UTF-8编码存档的,使用UTF-8解码也同样是乱码,相信很多人遇到类似的问题,我这里解决 ...

  8. 算法训练营 重编码_参加编码训练营之前要考虑的7件事

    算法训练营 重编码 Coding bootcamps are becoming more and more popular, and for good reason. Just picture you ...

  9. tcp选项部分编码_学习编码中最难的部分也是最有趣的部分

    tcp选项部分编码 by Corey Slaven 通过Corey Slaven 学习编码中最难的部分也是最有趣的部分 (The hardest part of learning to code is ...

最新文章

  1. Java文件字节流和字符流FileInputStream,FileOutputStream,FileReader,FileWriter
  2. wps office oa控件 痕迹_WPS,Excel,哪个好用?其实真的好用的,是这个工具
  3. 团队作业(四):描述设计
  4. linux之一些比较新但是常用的命令(expr ag tree cloc stat tmux axel)
  5. arm32和arm64常用指令B BL BLX机器码计算
  6. SharePoint 解决管理员密码修改后的问题
  7. 中国能源统计年鉴资源网站
  8. webstorm小程序插件和中文插件
  9. html input属性都有啥,input 属性有哪些input标签常用属性
  10. endnote 参考文献加序号_两招搞定参考文献自动编号与格式编排
  11. 集群通信:从心跳说起
  12. 小知识·PD充电协议
  13. Layman数字土地指南
  14. 区分触摸屏种类的几种方法
  15. JMeter-接口自动化测试读取用例,执行并结果回写
  16. python利用numpy模块读取csv文件
  17. android视频gif编辑器,GIF制作编辑
  18. 自然语言处理之Word2Vec
  19. (一)jenkins+bonobo git server+windows系统自动化部署springboot项目(jenkins安装)
  20. Artifact storage:war exploded: Error during artifact deployment. See server log for details 之一种解决方法

热门文章

  1. Scala数组的基本操作,数组进阶操作,多维数组
  2. ubuntu16.04 安装docker-ce,解决libltdl7版本过低的问题
  3. JVM调优系列:(二)JVM运行时数据区域
  4. HashMap与垃圾回收
  5. Linux RHCS中心跳网络接口的指定
  6. pt-archiver 数据归档bug
  7. 关于Javascript框架的神回帖,值得围观
  8. 在MFC框架下使用osg报内存泄露的解决办法
  9. socket.io 中文手册 socket.io 中文文档
  10. 网站用sqlite库,报attempt to write a readonly database,解决方法