如何编写更高效的代码

时间:2010-08-27 17:20:43

标签: c performance premature-optimization

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

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

12 个答案:

答案 0 :(得分:21)

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

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

答案 1 :(得分:9)

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

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

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

答案 2 :(得分:7)

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

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

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

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

答案 3 :(得分:3)

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

答案 4 :(得分:2)

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

答案 5 :(得分:2)

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

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];

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

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

答案 6 :(得分:1)

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

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

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

在此之后的某个地方,您可以开始担心性能问题。

答案 7 :(得分:1)

本世纪的答案是

  

不要把马放在马前。

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

每个人都“知道”这一点,但关于SO的一大类问题的形式是“哪个更快,X或Y?”

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

答案 8 :(得分:0)

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

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

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

答案 9 :(得分:0)

寻找更正确的方法 - 使用循环和数组 - 这两种情况都不会导致更多的内存使用(使用量减少,因为所有car1,car2,car3 ...指令所需的内存将更多) - 和CPU使用情况一样,你会看到最小的差异。

答案 10 :(得分:0)

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

有些工具可以像gprof这样的开源来使用。

答案 11 :(得分:0)

我通常不担心效率......

如果我搜索数值,那么加快速度的地方就是其中之一 我想找一个帐号&#34; 188335344&#34;它会比搜索字母字符快得多。搜索必须在搜索非数字值时将每行文本切换为大写。数字并非如此。

实际上要快一点。

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

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