5

我有 5 个函数,它们被调用了 10000 多次(平均)。它们都修改/使用某些变量。

我知道拥有全局变量是不好的做法。但是出于性能考虑,将它们保持全局而不是传递它们是否有意义 - 特别是当我多次调用函数时?

或者我不会在性能方面获得太多收益?

4

7 回答 7

7

不要出于性能目的引入全局变量/全局状态。这是被误导的,与所有良好的编码实践相反,并且通常不会提高性能(甚至可能会受到伤害)。

如果您发现传递大量变量的成本太高,您可以将它们全部放在一个上下文中struct,然后将单个指针传递给struct. 这样您就可以避免创建全局状态(即使static存储持续时间变量也是全局状态),这会阻止您的代码在多个实例中可用。成本几乎为零,实际上它比位置无关代码(共享库或位置无关可执行文件)中的全局变量成本更低。

于 2011-07-14T00:19:54.857 回答
5

通过减少传递给函数的参数数量,通过预分配变量(例如,全局或静态变量),您可能会看到性能的小幅提升

性能的变化绝对取决于许多因素,其中最重要的是您正在开发的平台。如果您正在为微型微处理器开发,则将参数复制到堆栈(从调用函数)所花费的时间以及访问堆栈所花费的时间可能占总执行时间的很大一部分,以保证它。

请注意,在传递参数所花费的时间很长的情况下,您可能会发现其他一些建议(例如,传递指向结构的指针、传递指向静态变量的指针)也不会提供任何好处。使用全局变量确实使编译器/链接器有机会硬编码访问这些变量,而不必从堆栈上的指针间接访问它们。这尤其适用于没有任何缓存的处理器。

当然,这一切都非常依赖于目标,并且高度依赖于您正在使用的处理器的指令集。在任何具有合理指令集的平台上,您都应该看到改进。

但是,只有在分析此代码后才应采取此类措施。在大多数平台上,对于任何重要的功能,传递参数和访问它们所花费的时间都是微不足道的。任何潜在的性能提升都将以代码维护更加困难为代价。

通过使用其他优化技术,您很可能会获得更大的性能提升。检查问题以尝试一些方法。


编辑:我从您的一条评论中看到您仍处于该项目的设计阶段。

现在进行这样的优化还为时过早。在这个阶段,通过优化您使用的算法,您将对性能产生更大的影响,而不是像这样在指令级别最小化。

于 2011-07-14T01:02:03.543 回答
3

静态变量是 C 具有文件范围,在您的情况下它们可能就足够了 - 只要您可以将函数分组到 1 个文件中。对我来说,静态变量的问题比全局变量小几个数量级。

一个经常被忽视的问题是,在函数体内声明的变量将在堆栈上分配,而静态变量通常是从称为 bss 的不太受限的内存池中分配的。因此,在函数内部整齐地定义所有变量可能会导致堆栈耗尽问题,而这可以通过使用静态的非常干净的方式来避免。

于 2011-07-14T00:11:14.580 回答
2

在某些嵌入式微控制器上,使用全局变量而不是参数可能会带来性能优势,但这与机器高度相关

例如,当使用典型的 8 位微控制器编译器 (HT-PICC18) 时,设置全局变量的成本是每字节两条指令/两个周期。传递一个单字节参数需要花费指令/一个周期。传递两个或更多字节的参数每个字节花费两个周期。因此,传递两个单字节参数的最有效方法是将一个作为参数传递,一个作为全局参数传递。

在 68HC11 的 Introl 编译器上,具有任何自动变量或参数的例程需要多指令序言和结尾,如果所有变量都是静态的并且参数作为全局变量传递,则可以省略它们。但是,如果例程将使用任何局部变量或参数,那么在其他所有内容中使用局部变量和参数的边际成本可以忽略不计。

在 ARM 上,即使没有缓存,也经常出现相反的情况:访问自动变量或参数通常比访问全局变量要快。自动变量和参数将位于寄存器中,或者位于寄存器中存储的地址的可直接访问的已知偏移量处。相比之下,访问全局变量通常需要两个步骤:首先加载全局变量的地址,然后访问变量本身。

于 2012-02-09T16:18:08.760 回答
2

我什至会说全局变量可能会比传递参数慢。参数存在于堆栈中,该堆栈被大量使用,因此很可能在缓存中。全局变量位于静态空间中,使用较少,因此不太可能在缓存中,从而使内存查找速度变慢。由于缓存考虑,您的跳转(到新函数)很可能是整个函数调用操作中最慢的部分。

如果您的功能很小,请查看内联它们。如果它们很大,那么将一两个单词压入堆栈的可能性很小。

另请注意,使用堆栈进行参数传递在很大程度上是 x86 的事情。ARM 和其他具有大量寄存器的架构通常会使用一些寄存器进行参数传递,速度非常快。

于 2011-07-14T00:23:39.837 回答
1

人们通常会尽量远离全局参数,除非他们真的需要它们(即,除非某些东西真正具有全局状态)。特别是对于多线程应用程序,使用全局参数会使事情变得比实际需要的更加困难。

在性能方面,我听到一些人暗示在某些情况下访问全局变量可能会更快,尽管我觉得很难相信,但唯一可以确定的方法是为您的特定情况实际做一些基准测试。

就个人而言,我永远不会这样做。我会考虑将参数传递给函数的方式(确保它是通过指针,而不是通过复制,例如,在大数据类型的情况下)并确保将正确的(最佳)优化设置传递给编译器。

希望这可以帮助。

于 2011-07-14T00:22:50.957 回答
0

我认为您不会通过用全局变量替换参数来提高性能。

无论如何,如果你想这样做,你也可以考虑在同一个文件中声明所有函数和变量,并将变量声明为静态。这样,只有在同一文件中声明的函数才能访问它们。

看这里

于 2011-07-14T00:12:35.887 回答