【发布时间】:2017-12-04 12:57:22
【问题描述】:
在玩 Go 中的一些简单代码时,我注意到使用 bool 数组而不是 int 数组(仅使用 0/1 的值)具有相当显着的加速。
- funcUsingBool - 1.397s
- funcUsingInt - 1.996s
我希望它们都提供相同的性能,因为在机器级别没有本机 bool 类型,所以我希望编译器生成类似的汇编代码。
由于差异很大,我对这个结果的有效性持怀疑态度。
我正在使用命令“go build filename.go”进行构建,但我不确定 gcc 的“-O3”的等效标志是什么。
func funcUsingBool(n int) int {
if n < 1 { return 0 }
notPrime := make([]bool, n+1)
count := 1
for i := 3; i < n; i = i + 2 {
if notPrime[i] { continue }
count++
k := 2 * i
for k <= n {
notPrime[k] = true
k += i
}
}
return count
}
func funcUsingInt(n int) int {
if n < 1 { return 0}
notPrime := make([]int, n+1)
count := 1
for i := 3; i < n; i = i + 2 {
if notPrime[i] == 1 { continue }
count++
k := 2 * i
for k <= n {
notPrime[k] = 1
k += i
}
}
return count
}
【问题讨论】:
-
为什么在使用不同大小的值时不会有一些差异?
-
没有原生 bool 类型,是的,但这仍然使 bool 1 字节和 int 4 或 8 字节。
-
对问题的分数感到惊讶(否定)。严肃的问题:我是否会降低“GO-ers”对一个琐碎话题的期望讨论水平,应该在其他地方问这样的问题,还是我的措辞很差和缺乏?
-
@twosan:x86(和大多数其他 CPU)可以有效地处理字节元素。在当前的 Intel CPU 上,将字节的零扩展或符号扩展加载到 64 位寄存器中与 4 字节或 8 字节的加载一样便宜。字节商店也很便宜。只有早期的 Alpha AXP CPU 只能加载对齐的字,并且必须移位/屏蔽才能获取字节。
-
使用位图会更昂贵,因为将位设置为
true需要对包含它的字节进行读取-修改-写入,这比简单的存储更昂贵。但是,当您的阵列变得足够大时,这是值得的,因为在 L1 或 L2 缓存中安装以避免缓存未命中是值得的,每次写入操作的额外 CPU 开销都是值得的。 (从内存中测试一个位仍然很便宜,尤其是在 x86 上)。
标签: performance go