全局变量有计算效率吗?

计算科学 效率
2021-12-18 14:36:48

我特别想知道诸如大型游戏树之类的递归函数。我还不能具体说有多大,但肯定会突破给定处理器或处理器阵列的极限。

是否正确地说将变量传递给函数需要操作。当然必须有一些位的翻转。这会降低效率吗?

3个回答

首先,请注意,这个论坛是针对计算科学的,而不是计算机科学的。这些是不同的领域,计算科学是科学计算,更像是计算数学和科学模拟。也就是说,即使有问题的示例与本论坛无关,也有一些事情应该在这里讨论。

低效率不在于将值传递给函数,而在于许多其他地方。这是因为全局变量可以随时更改。程序无法知道值是否会改变,更重要的是在脚本语言中,它们可以改变类型。因为程序不知道变量是否发生了变化,所以程序必须准备好处理发生的任何事情。因此,所有编译器/解释器优化都被关闭,变量周围的任何代码都必须进入“安全模式”

例子

一个很好的例子是看 Julia。Julia 是一种最近的编程语言,虽然它“看起来像一种脚本语言”,但实际上它的设计目的是在每一步都可以高效地编译。如果您正确编写 Julia 代码(类型稳定等),那么您的代码将编译为与 C/Fortran 相同的速度(并且您可以使用它@code_llvm来查看机器代码与您得到的相同)来自 C/Fortran 编译器)。但是,该语言在全局变量方面存在问题。在 Github 上可以找到关于原因的大型讨论总结如下:

在像 Julia 这样的(即时)编译语言中,编译器会查看它当前拥有的内容并使用一系列技巧来优化代码。但是,如果它不一定知道变量是什么类型,它必须携带一堆代码来使其在整数/浮点数/等之间切换。如果变量是全局变量,它还必须处理其他线程是否更改了值等问题。这意味着许多其他编译器技巧(如内联)也无法完成。因此,生成的编译代码有更多的步骤来检查每个小细节,因为全局几乎可以做任何事情。这使得与他们打交道的效率非常低。

当您爬上阶梯以获得更动态的输入时,这些低效率会更多地融入到语言中。在底部,所有语言仍在运行已编译的代码,所以像 MATLAB/R/Python 这样的东西总是有这个额外的代码,因为它们的数字可以一直改变类型(Javascript 也可以,虽然这很奇怪,因为“一切都是浮点数"所以它必须让部分在正确的时间将事物转换为整数)。然而,智能解释器(如 Javascript JIT)有时仍会尝试进行一些优化,但出于与上述相同的原因,当存在全局变量时,它们也无法进行过多优化,因为实际上无法提前知道全局变量是什么变量将是(类型和值)。当所有赌注都关闭时,他们必须安全行事。

(另一个方向的例子,如果你传入一个变量,它看起来像一个整数,并且所有代码看起来都不会修改它,它可以 JIT 编译函数,使其实际上是一个整数,导致更精简和更有效的机器代码。请注意,这要求编译器可以保证此变量不会在其他任何地方更改,否则会导致损坏。)

结论

这就是为什么效率的一般规则是不使用全局变量。解释器/编译器无法知道如何处理它们,因此它们必须采取最安全且效率最低的路线。此外,由于它们可以随时随地更改,它们可能会导致程序中出现很多错误,因此出于设计原因,全局变量通常不受欢迎。最后,除非你真的必须这样做,否则不要使用 GLOBALS。

tldr; 将变量传递给函数将导致比全局变量少得多的问题。

这更像是 Stack Exchange 或 Programmer Exchange 问题,请参阅: 此处了解 C 语言PHPJavascriptC++,以及 更普遍的情况。

尽量避免全局变量。更好地维护您的代码。全局变量应该是参数,即它们的值在执行过程中不应该改变。关于效率,我认为这是一个不太相关的微观优化。我不是专家,但我认为使用函数参数而不是全局变量可以让编译器进行更多优化(堆栈和寄存器......)。将变量传递给函数只需要堆栈中的一些指针引用(假设您的全局变量不是一个巨大的对象),这非常快,我什至不确定分析器是否可以检测到这样的事情。

风格的角度来看,通常最好避免使用全局变量(如前所述)。

从性能的角度来看,答案取决于您的编程语言。例如,如果您的语言不支持通过引用传递多维数组,那么全局/非本地数组可以提供帮助。但我想所有用于计算的现代语言都没有这样的缺点。

当一个函数有更多参数时调用它是否成本更高取决于语言和编译器。通常,额外成本为零或可以忽略不计,因此全局变量更有可能伤害而不是使您受益(如其他答案中所述)。