我发现gcc中的不同编译器优化级别在循环中访问本地或全局变量时会产生完全不同的结果.这让我感到惊讶的原因是,如果访问一种类型的变量比访问另一种变量更可优化,我认为gcc优化会利用这一事实.这里有两个例子(在C++中,但它们的C对应物实际上给出了相同的时间):
global = 0;
for (int i = 0; i < SIZE; i++)
global++;
Run Code Online (Sandbox Code Playgroud)
它使用一个全局变量long global,对
long tmp = 0;
for (int i = 0; i < SIZE; i++)
tmp++;
global = tmp;
Run Code Online (Sandbox Code Playgroud)
在优化级别-O0,时间基本相等(如我所料),在-O1它稍快但仍然相等,但是从-O2使用全局变量的版本要快得多(大约7倍).
另一方面,在下面的代码片段中,起始点指向大小为SIZE的字节块:
global = 0;
for (const char* p = start; p < start + SIZE; p++)
global += *p;
Run Code Online (Sandbox Code Playgroud)
与
long tmp = 0;
for (const char* p = start; p < start + SIZE; p++)
tmp += *p;
global = tmp;
Run Code Online (Sandbox Code Playgroud)
这里的-O0时间很接近,虽然使用局部变量的版本稍微快一点,这似乎并不太令人惊讶,因为它可能会存储在寄存器中,而global …
我一直在看一些Lua源代码,我经常在文件的开头看到这样的东西:
local setmetatable, getmetatable, etc.. = setmetatable, getmetatable, etc..
Run Code Online (Sandbox Code Playgroud)
他们是否只使本地函数让Lua在经常使用时更快地访问它们?
在Roberta Ierusalimschy的Lua编程(第3版)中说明了这一点
Lua的一个常见习语是
local foo = foo此代码创建一个局部变量,
foo并使用全局变量的值对其进行初始化foo.(foo只有在声明后,本地变得可见.)当块需要保留原始值时,foo即使稍后某些其他函数改变了全局值,这个习惯用法也很有用foo; 它还加快了访问速度foo.
有人可以更详细地解释这个并提供一个简单的例子吗?
目前,我能想到的唯一用途就是管理与全局变量具有相同名称的局部变量(在给定的块中),以便在块之后保持全局变量不变.
一个例子:
foo = 10
do
local foo = foo
foo = math.log10(foo)
print(foo)
end
print(foo)
Run Code Online (Sandbox Code Playgroud)
这给了:
1
10
Run Code Online (Sandbox Code Playgroud)
但是完全可以在不使用成语的情况下完成:
bar = 10
do
local bar = math.log10(bar)
print(bar)
end
print(bar)
Run Code Online (Sandbox Code Playgroud)
这给出了相同的结果.所以我的解释似乎并不成立.
我对此有几点想法.第一个是分配全局变量可能更快,因为它们在程序首次生成时只分配一次,而每次调用函数时都必须分配局部变量.我的第二个想法是,由于局部变量在堆栈上,它们是通过基址指针寄存器访问的,因此每次访问局部变量时,必须递减存储在基址指针中的值.全局变量可以通过数据段中的静态地址直接访问.我的想法准确吗?