3

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

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

对比

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?我基本上是想看看哪种是编写此代码的最有效方式。

谢谢, 半羊

4

12 回答 12

21

效率比可维护性和可读性更重要吗?答案是不。即使您有一个时间关键型应用程序,您也会将 90% 的时间花在不到 10% 的代码上,因此只有 10% 的代码需要尽可能高效地进行编码。

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

于 2010-08-27T17:25:59.610 回答
10

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

第二个问题是:值得优化吗?根据 Donald Knuth 的说法,在 97% 的情况下都不是——而且你不会质疑 Knuth,是吗?另一个常见的经验法则是 80/20 规则,即 80% 的执行时间花在 20% 的代码上。如果您要优化,首先要了解要优化的位置。如果你猜,你就错了。时期。

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

于 2010-08-27T17:37:15.980 回答
7

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

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

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

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

于 2010-08-27T17:26:59.017 回答
3

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

于 2010-08-27T17:48:37.397 回答
2

使用数组,使用 -funroll-loops 编译。你得到两者的好处。

于 2010-08-27T17:26:57.063 回答
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];

考虑到所涉及操作的成本和您提供的优化标志,编译器将对其是否值得这样做进行最佳猜测。

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

于 2010-08-27T17:27:30.373 回答
1

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

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

  1. 正确 - 如果代码给出错误答案或做错事,代码的速度并不重要;
  2. 可维护——如果你不能修复或修改它以适应新的需求,你的代码有多快都没有关系;
  3. 健壮——如果你的代码在第一个不可靠的输入提示时核心转储,那么它的速度并不重要;

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

于 2010-08-27T17:33:13.543 回答
1

世纪的答案是

不要本末倒置。

换句话说,首先配置文件。

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

这会引发猜测,当您关心性能时,猜测并不值得,因为如果您遇到性能问题,它可能完全在其他地方。

于 2010-08-30T15:55:36.320 回答
1

我通常不担心效率...

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

实际上快了一点。

任何需要用户输入的东西都可能效率极低,一点也不重要。

我会在每次搜索结束时显示经过的时间。因此,可以将较旧的代码与较新的更改进行比较。

于 2016-08-20T16:27:38.473 回答
0

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

一些这样做的工具可以作为开源工具使用,比如gprof

于 2010-08-27T19:59:58.320 回答
0

选择更正确的方法 - 这将使用循环和数组 - 两者都不会导致更多的内存使用(更少的使用,因为所有这些 car1、car2、car3 ......指令所需的内存会更多) - 和 CPU使用方面,您会看到最细微的差异。

于 2010-08-27T17:29:09.240 回答
0

与往常一样,您需要对您的代码进行概要分析才能确定。

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

在一个完全不相关的注释上,我看到你的车有高度。是飞行汽车吗?如果是这样,那么酷应用绝对是+1。

于 2010-08-27T17:26:25.063 回答