多线程和内存

时间:2009-11-03 10:28:28

标签: c++ multithreading cpu x86-64

我在Visual C ++文档中读到,多个线程从同一个对象读取是安全的。

我的问题是:具有多个内核的X86-64 CPU如何处理这个问题?

假设您有1 MB的内存块。不同的线程是否能够同时读取完全相同的数据,或者核心是否一次读取一个字,只允许一个核心一次读取一个特定的字?

2 个答案:

答案 0 :(得分:10)

如果1MB块中确实没有写入,那么每个核心都可以从其自己的缓存行读取而没有任何问题,因为没有提交写入,因此不会出现缓存一致性问题。

在多核架构中,基本上每个核心都有一个缓存和一个“缓存一致性协议”,它使一些没有最新信息的核心上的缓存无效。我认为大多数处理器都实现了MOESI protocol缓存一致性。

缓存一致性是一个复杂的主题,已经在很大程度上讨论过(我特别喜欢Joe Duffy herehere的一些文章)。尽管如此,讨论围绕着代码可能的性能损失,虽然显然是无锁的,但由于缓存一致性协议的开始可以减缓处理器缓存中的一致性,但是,只要没有写入,就没有保持一致性,从而不失性能。

正如在评论中所说的那样,不能同时访问RAM,因为x86和x64体系结构实现了一个单独的总线,它在SMP内核之间共享,保证了访问主内存的公平性。尽管如此,每个核心缓存都隐藏了这种情况,这允许每个核心拥有自己的数据副本。对于1MB的数据,当核心更新其缓存时,可能会产生一些争用,但这可以忽略不计。

一些有用的链接:

答案 1 :(得分:5)

不仅允许不同的内核从同一块内存中读取,它们也可以同时写入。如果它是“安全的”,那是一个完全不同的故事。你需要在你的代码中实现某种防护(通常用信号量或它们的衍生物来完成),以防止多个内核以你没有特别允许的方式在同一块内存上作战。

关于核心一次读取的内存大小,通常是寄存器的值,32位cpu为32位,64位cpu为64位,依此类推。甚至流式传输也是通过dword完成的(例如,请查看memcpy)。

关于并发多核的实际情况,每个核使用单个总线来读写内存,因此访问任何资源(ram,外部设备,浮点处理单元)是一次一个请求,一个核心一次。然而,核心内部的实际处理是完全并发的。 DMA传输也不会阻塞总线,并发传输一次排队并处理一个(我相信,不是100%肯定)。

编辑:只是为了澄清,与此处的其他回复不同,我只谈论无缓存方案。当然,如果内存被缓存,则只读访问是完全并发的。