代码优化

时间:2009-08-14 22:19:47

标签: c optimization

如果我有一个很大的结构(有很多成员变量)。这个结构指针传递给我的代码中的许多函数。在几乎所有函数中,这种结构的一些成员变量经常被使用。

  1. 如果我将那些经常使用的成员变量放在结构声明的开头,它是否会优化MCPS的代码 - 每秒百万个周期(代码消耗的时间)。如果我按时将频繁访问的成员放入,那么它们是否会被有效/更少地访问,而不是将它们随机地放在结构声明底部的结构中?如果是,逻辑是什么?

  2. 如果我在某个函数中访问了一个结构成员,如下所示:

    structurepointer1-> member_variable

  3. 如果我将它分配给局部变量然后访问局部变量,它是否有助于在MCPS方面进行优化?如下所示?

    local_variable = structurepointer1->member_variable;
    

    如果是,那么它有何帮助?

8 个答案:

答案 0 :(得分:14)

1)结构中字段的位置应该对其访问时间没有影响,除非您的结构非常大且跨越多个页面,最好定位常常的成员用于快速连续关闭以增加引用的局部性并尝试减少缓存未命中。

2)也许/也许不是。事实上它可能会让事情变得更慢。如果变量不是易失性的,那么编译器可能足够聪明,无论如何都要将字段存储在寄存器中。即使没有,你的处理器也会缓存它的值,但如果使用距离相差太远,那么这可能无济于事,其间还有很多其他内存访问。如果该值已存储在寄存器中或将保留在处理器的缓存中,则将其分配给本地只会是不必要的额外工作。

标准优化免责声明:在优化之前始终进行配置。确保您要优化的内容值得优化。始终对您尝试过的优化进行概述,并确保它们实际上更快(而不是更慢)。

答案 1 :(得分:7)

首先,强制性免责声明:对于所有性能问题,您必须对代码进行分析,以了解可以在何处进行改进。

一般而言,将数据保存在处理器缓存中的任何操作都会有所帮助。将最常访问的项目放在一起将有助于实现这一点。

答案 2 :(得分:3)

我知道这并没有真正回答您的问题,但在您深入研究超级优化代码之前,请先阅读此演示文稿http://dl.fefe.de/optimizer-isec.pdf。我看到它现场直播,这是一个良好的开放体验,显示编译器在优化方面比我们想象的要先进得多,并且可读代码比小优化更重要。

在2上,你最好不要声明一个局部变量。编译器通常足够聪明,可以确定何时以及如何使用变量,并利用寄存器来保持变量。

此外,我会在Mark Ransom的建议中提出建议,在对瓶颈进行假设之前对代码进行概述。

答案 3 :(得分:2)

我认为您的问题与数据对齐和数据结构填充有关。在现代编译器中,大多数时候会自动处理,试图避免可能在内存上发生的对齐错误。你可以阅读这个here。当然,您可以更改数据的对齐方式,但我认为您需要指定一些编译器选项来禁用自动对齐,并重新排列结构上的字段以匹配您的目标体系结构。

我想说这是一个非常低级别的优化。

答案 4 :(得分:0)

  1. 结构中字段的位置无关紧要,因为它将由编译器计算。更有前途的优化是确保最常用的字段与处理器的字大小字节对齐。

  2. 如果您正在使用函数的local变量,那么这应该没有影响。如果你将它传递给其他功能(与较大的结构分开),那可能会有所帮助。

答案 5 :(得分:0)

与所有其他答案一样,您需要在优化之前运行配置文件基线,以确保更改生效。如果您担心执行时间,请在您担心编译器创建的代码之前对算法进行概要分析并对其进行优化,这样可以获得更多优势。

另外,如果你想知道将要发生什么,你应该考虑将你的c代码编译成汇编输出。这将让您了解编译器将要执行的操作以及如何进一步“微调”。

  1. 结构访问通常是索引间接访问。汇编代码将有效地提取内存,知道指向结构的指针作为基数加上和索引来获得正确的字段。这通常是一项昂贵的操作,但对于现代CPU来说,它可能并不那么慢。

  2. 这取决于所访问数据的位置。首先,首次访问该结构将是最昂贵的。如果数据已经在处理器寄存器中,则可以快速访问数据,但是,根据所使用的处理器,情况可能并非如此。存储到本地变量应该更便宜,因为用于这种操作的存储器访问指令更便宜。同样,我认为现在处理器的速度足够快,这种优化很少。

  3. 我仍然认为可能有更好的地方来优化您的代码。虽然在某个代码臃肿的世界里仍然有人在考虑这个问题,但这很好;)嵌入式计算,你仍然需要担心这些事情。

答案 6 :(得分:0)

  1. 这取决于字段的大小和缓存详细信息。看看使用valgrind进行分析。
  2. 如果你做这个解除引用很多,那将花费时间。如您所述,一个不错的优化编译器将有效地将指针存储到局部变量优化中。它将比你做得更好,它将以特定于架构的方式完成。

  3. 总体而言,在这种情况下,您要做的是确保测试正在尝试的每个优化的正确性和性能。否则你在黑暗中四处寻找。

    请记住,C行级别的精细优化几乎不会胜过高阶算法/设计优化。

答案 7 :(得分:0)

是的,它可以提供帮助。但正如人们已经说过的那样,这取决于甚至可能适得其反。 我认为它可以帮助的原因,与指针别名有关。如果通过指针访问变量,并且编译器无法保证结构没有在其他地方(通过指针或其他)更改,他将生成代码以重新加载或保存变量,即使他可以将值保存在寄存器中。这是一个显示我的意思的例子:

calc = structurepointer1->member_variable * x + c;    
/* Do something in function which doesn't involve member_variable; */
function(structurepointer1);    

calc2 = structurepointer1->member_variable * y;

编译器将对member_variable的两个引用进行内存访问,因为它无法确定被调用函数是否已修改该字段。 如果您确定该函数不会更改该值,则执行此操作将节省1次内存访问

int temp = structurepointer1->member_variable;
calc = temp * x + something;
function(structurepointer1);
calc2 = temp * y;

还有另一个原因可以为成员变量使用局部变量,它可以使代码更具可读性。

相关问题