如何编写更高效的代码

世纪的问题? 我基本上想知道如果我将这段代码写成几个不同的变量或者我使用的是小数组,哪个会更有效。

int x = 34; int y = 28; int z = 293; 

VS

 double coordinate[3] = {34, 28, 293}; 

我有一个坐标结构,我将按以下方式使用:

 typedef struct coordinates_t { double x = 0.0; double y = 0.0; double z = 0.0; } coordinates; typedef struct car_t { coordinates start; // car starting point coordinates location; // car current Location coordinates targCarVector; // Vector to car from target coordinates altitude; // Altitude of car coordinates distance; // Distance from car start to current position } car; 

我需要做的事情如下:

 distance = car1.location - car1.start; 

如果我不使用数组,我将不得不有很多行代码,但如果我使用数组,我将不得不使用循环。 数组和循环是否更多内存/ CPU密集? 我基本上试图看看哪种是编写此代码的最有效方法。

谢谢,DemiSheep

第一个问题是: 你想优化它吗? 最有可能的是,你不想这样做。 至少不会,如果你“始终编码,好像最终维护你的代码的人会是一个知道你住在哪里的暴力精神病患者”。 可读性,意图清晰度和可维护性始终是第一位的。

第二个问题是: 值得优化吗? 根据唐纳德·克努特的说法,97%的情况并非如此 – 你不会质疑克努特,对吗? 另一个常见的经验法则是80/20规则,即80%的执行时间花费在20%的代码中。 如果您完全优化,请首先了解要优化的位置。 如果你猜,你错了。 期。

第三个问题是: 你能优化吗? 不,你不能,至少不是这么容易。 您认为自己比数百年编写编译器的程序员更聪明吗? 你不是。 如果可以优化算法和数据结构的实际实现,则可以假设编译器可以自行完成。 编译器可以进行循环展开,指令重新排序,组合具有非重叠生命周期的变量,结构布局优化等等 – 在这个时代,它在大多数情况下甚至比大多数汇编程序员更好。 即使有一点潜力,你最好专注于实现更好的算法。 没有编译器可以将O(n ^ 2)转换为O(n log n),但也许是智能计算机科学家做到了这一点,你可以实现他的算法,以获得比任何微优化都能产生的更好的性能。

效率对可维护性和可读性更重要吗? 答案是不。 即使您有一个时间要求严格的应用程序,您将花费90%的时间在不到10%的代码中,因此只有10%需要尽可能高效地编码。

如果您还没有测量并发现哪个是10%是罪魁祸首,那么您几乎肯定会优化代码,这些代码首先不需要太多的运行时间。 这是浪费时间。

您必须为每个要执行此操作的平台进行测量。

但是我不认为这会产生任何明显的差异。 (也许除了一些嵌入式平台。这是一个我不太了解的领域。)所以首先以最容易阅读和理解的方式编写代码 。 然后测量你的代码是否要慢,并使用分析器找到程序花费很多时间的确切位置 。 然后尝试改进这些,在每次更改后测量,看看它有哪些效果。

提高易于理解的代码库的速度要比理解过早和不需要的“优化”的代码库容易得多。

可衡量的运行时间改进通常来自算法更改 ,而不是像这样的微优化。 花时间试图找到更好的算法。

如果您真的想要对其进行微优化,请使用CPU的SIMD指令function。 如果您使用的是x86平台,则可以使用MMX或SSE指令进行向量运算,而不是单独添加坐标的每个部分(如果没有特殊的命令行开关或内联汇编,编译器可能无法生成这些部分)。 这可能比单个变量和数组之间切换的速度更快。 我说“可能”,因为如果不尝试两种方式并测量执行时间,就无法确定。

使用数组,使用-funroll-loops进行编译。 你可以从中获益。

编译器可以“展开”循环,如果他们认为它会有所帮助。 所以编译器可能会悄悄地替换以下代码:

 for (i = 0; i < 3; ++i) { c[i] = a[i] - b[i]; } 

有:

 c[0] = a[0] - b[0]; c[1] = a[1] - b[1]; c[2] = a[2] - b[2]; 

编译器将考虑所涉及的操作的成本和您提供的优化标志,最好地猜测它是否值得这样做。

对于“哪一个会更快?”没有简单的答案,但是如果有,你可以确定通过最大程度的优化,你的编译器会使用它。

如有疑问,请为每个原型编制原型并对其进行分析。 对于这个级别的东西,我会预测性能的任何差异都会降低噪音。 使用有意义的东西 ,最明确地传达设计的意图。

按重要性降序排列,代码必须是

  1. 正确 – 如果你的代码给你错误的答案或做错了什么,那么代码的速度并不重要;
  2. 可维护 – 如果您无法修复或修改代码以满足新要求,则代码的速度无关紧要;
  3. 强大 – 如果核心在第一次狡猾的输入提示上转储,那么代码的速度并不重要;

在此之后的某个地方你可以开始担心性能。

本世纪的答案是

不要把车放在马前。

换句话说,首先是个人资料。

每个人都“知道”这一点,但SO上的一大类问题的forms是“哪个更快,X还是Y?”

这引出了猜测,当你关注性能时,猜测并不值得,因为如果你有性能问题,那么它可能完全在其他地方。

与往常一样,您需要对代码进行分析以确定。

话虽如此,我建议去一个数组和循环 – 你的代码应该更简洁/可维护,编译器应该能够很好地优化/展开所有小的常量循环,这实际上是什么如果你对每个向量使用x,y,z坐标,你会用手做。

在完全不相关的说明中,我看到你的车有高度。 这是一辆飞行汽车吗? 如果是这样,那么绝对+1适用于酷应用程序。

寻找更正确的方法 – 使用循环和数组 – 这两者都不会导致更多的内存使用(更少的使用,因为所有car1,car2,car3 …指令所需的内存将更多) – 和CPU使用方面,你看看最小的差异。

请分析您的代码,找出效率低下的主要问题。 效率可以通过代码的运行时执行来衡量。

有些工具可以像gprof这样开源。

我通常不担心效率……

加快速度的一个地方是,如果我搜索数字值说我想找到一个帐号“188335344”,它会比搜索字母字符快得多。 搜索必须在搜索非数字值时将每行文本切换为大写。 数字并非如此。

实际上要快一点。

任何需要用户输入的内容都可能非常低效,并且无关紧要。

我会在每次搜索结束时显示已用时间。 因此可以将旧代码与最近的更改进行比较。