Memory 为什么原子操作使用独立线程更快?
我有两段代码,桌面上有32个内核 代码A使用32个线程并执行以下操作 1将值写入内存中的一些随机位置 2以原子方式向全局变量添加值 代码B使用16个线程将值写入随机位置,并使用另外16个线程将值自动添加到全局变量 我想知道为什么代码B在每秒对全局变量执行多少原子操作方面更快 这是代码AMemory 为什么原子操作使用独立线程更快?,memory,go,concurrency,cpu,cpu-cache,Memory,Go,Concurrency,Cpu,Cpu Cache,我有两段代码,桌面上有32个内核 代码A使用32个线程并执行以下操作 1将值写入内存中的一些随机位置 2以原子方式向全局变量添加值 代码B使用16个线程将值写入随机位置,并使用另外16个线程将值自动添加到全局变量 我想知道为什么代码B在每秒对全局变量执行多少原子操作方面更快 这是代码A var a uint64 = 0 const N = 10 * 1024 * 1024 var data [N]uint64 func main() { for i := 0; i < 32
var a uint64 = 0
const N = 10 * 1024 * 1024
var data [N]uint64
func main() {
for i := 0; i < 32; i ++ {
go func(id int) {
source := rand.NewSource(int64(id))
local_rand := rand.New(source)
for {
atomic.AddUint64(&a, uint64(1))
data[local_rand.Int31n(N)] = uint64(1)
}
}(i)
}
var b uint64 = 0
for {
c := atomic.LoadUint64(&a)
fmt.Println(c - b)
b = c
time.Sleep(time.Second)
}
}
这是代码B
var a uint64 = 0
const N = 10 * 1024 * 1024
var data [N]uint64
func main() {
for i := 0; i < 16; i ++ {
go func(id int) {
source := rand.NewSource(int64(id))
local_rand := rand.New(source)
for {
data[local_rand.Int31n(N)] = uint64(1)
}
}(i)
}
for i := 0; i < 16; i++ {
go func() {
for {
atomic.AddUint64(&a, uint64(1))
}
}()
}
var b uint64 = 0
for {
c := atomic.LoadUint64(&a)
fmt.Println(c - b)
b = c
time.Sleep(time.Second)
}
}
原子操作是昂贵的。为了维护原子性,您需要确保该代码块的执行是互斥的。通常,这是通过使用诸如加载链接、存储条件等指令实现的。在代码A中,有32个原子操作,但在代码B中,只有16个。减少原子工作,减少执行时间
作为一个实验,试着用代码A中的内存操作改变原子操作的顺序。只需先做内存,然后再做原子操作。您应该看到执行时间的减少。我不认为将代码a中的线程数更改为16可以提高性能。我看不出与您建议的有什么不同。首先是记忆,然后是原子。我错过了什么吗?如果所有线程都先执行原子,那么它们都将争夺锁。若你们先有内存,他们都会先有内存,不管缓存和否,内存操作都会在不同的时间完成。这意味着原子操作将在不同的时间开始。因此,您将不会有与先前相同的争论。所以我希望执行时间更短。可能是你所有的数据都被缓存了,没有达到我的预期。。不管怎么说,我脑子里闪过一个理论。你可以试试另一个实验。产生32个线程,让奇数线程执行内存,偶数线程执行原子。现在您应该看到与代码B相同的时间。我的意思是这两个操作在for循环中。顺序真的重要吗?我无法使用我的笔记本电脑,所以我无法尝试你所说的。