多重 for 循环,如何提高效率?

共 733字,需浏览 2分钟

 ·

2020-12-23 08:12

2258 字 14 图 : 文章字数

6 分钟 : 预计阅读

网络 : 内容来源

BabyCoder : 编辑整理




前言

  我在《华为 C 语言编程规范》中看到了这个:当使用多重循环时,应该将最忙的循环放在最内层。如下图:

  由上述很简单的伪代码可以看到,推荐使用的方式是:外小内大的方式。也就是内层循环是最忙的。

  然后我又在另外一份编程规范手册中,看到了类似的要求,如下图:

  看到了这个小技巧之后,我迫不及待的分享给我的小伙伴,后来闲下来的时候,就想自己做个测试,验证一下是否真的是这样。

Ubuntu 测试

  使用 Ubuntu 14.04 的系统进行测试,基本信息如下:

  • 系统版本:Ubuntu14.04
  • gcc 版本:4.8.2

  我使用了两份不同的代码文件进行测试,第一份是 外大内小 的代码,如下:

#include #include #include #include #include 
using namespace std;
int main(){ struct timeval tv; unsigned long ulStartTime, ulEndTime;
gettimeofday(&tv, NULL); // 获取当前时间 ulStartTime = tv.tv_sec * 1000000 + tv.tv_usec; // 计算当前起始时间 cout << "start time = " << ulStartTime << endl; // 打印显示 for(unsigned int i = 0; i < 1000000; i++) // 测试代码 { for(int j = 0; j < 100; j++) { } } gettimeofday(&tv, NULL); ulEndTime = tv.tv_sec * 1000000 + tv.tv_usec; // 计算结束时间 cout << "end time = " << ulEndTime << endl; // 打印结束时间 cout << "Time = " << ulEndTime - ulStartTime << endl; // 计算时间差值 微秒 us}

  执行上述代码,运行结果如下,耗时:165280us

  接着,我又准备了另外一份 外小内大 的代码,对比只是调换了 for 循环内外层的循环次数而已,如下:

#include #include #include #include #include 
using namespace std;
int main(){ struct timeval tv; unsigned long ulStartTime, ulEndTime;
gettimeofday(&tv, NULL); ulStartTime = tv.tv_sec * 1000000 + tv.tv_usec; cout << "start time = " << ulStartTime << endl; for(int i = 0; i < 100; i++) { for(unsigned int j = 0; j < 1000000; j++) {
} } gettimeofday(&tv, NULL); ulEndTime = tv.tv_sec * 1000000 + tv.tv_usec; cout << "end time = " << ulEndTime << endl; cout << "Time = " << ulEndTime - ulStartTime << endl;}

  上述代码的执行结果如下,耗时:155960us

  对比上述两份代码的运行结果,可以很明显的看到,外小内大效率更高一点!

  不过,你以为这就结束了吗?

树莓派测试

  手边刚好有一台树莓派,前段时间刚安装了最新的官方系统,就想着拿来做一下测试,基本信息如下:

  • 树莓派系统版本:buster
  • g++ 版本:8.3.0

  测试代码与在 Ubuntu 上运行的代码保持一致,这里就不重复贴代码了,只看一下运行结果。

  下边这个是 外大内小 的,运行结果如下,耗时:1214569us

  这个是 外小内大 的,运行结果如下,耗时:1345193us

  完了,可以很明显的看到,外大内小 的运行效率要更高一点。

问题分析

  我也是有点蒙逼的,不知道为啥会出现截然相反的情况,对比两个系统版本,硬件设备来看,推测原因有如下几种可能:

  • 处理器架构不同

    • Ubuntu 是安装在 win10 台式机上的虚拟机中,所使用的硬件应该为台式机的硬件(处理器等);而台式机的硬件是英特尔的 X86 架构的处理器。
    • 树莓派使用的硬件平台,是一个 ARM 架构的芯片,具体可以参考图片:
图片来源:树莓派实验室
  • gcc 版本不同,在刚开始操作的时候,也详细的列出了当前程序使用的环境
    • Ubuntu14.04 中 gcc  版本为:4.8.2
    • 树莓派中 gcc 版本为:8.3.0

  目前能想到的差异就这么多,其他的暂时还不知道,难道这个就是运行在 X86 平台和 ARM 平台的区别之一?更多的更深入的研究还有待后续学习研究才能知道。今天的讨论就到这里为止吧!

总结

  1. 在 X86 架构平台下,外小内大效率较高;
  2. 由于参考的规范手册,可能是用于服务器开发,而服务器仍然是 X86 架构的处理器居多,因此 for 循环的多重循环规则较适用;
  3. 需要考虑在嵌入式等 ARM 平台下,此规则是否同样适用,是否还有其他应用场景限制等?欢迎私信/加我好友一起讨论~



推荐阅读:
专辑|Linux文章汇总
专辑|程序人生
专辑|C语言
我的知识小密圈

浏览 17
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报