Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Memory 为什么原子操作使用独立线程更快?_Memory_Go_Concurrency_Cpu_Cpu Cache - Fatal编程技术网

Memory 为什么原子操作使用独立线程更快?

Memory 为什么原子操作使用独立线程更快?,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

我有两段代码,桌面上有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; 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循环中。顺序真的重要吗?我无法使用我的笔记本电脑,所以我无法尝试你所说的。