多线程和内存

8

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

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

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

2个回答

13
如果在您的1MB块中真的没有写入操作,那么是的,每个核心都可以从自己的缓存行读取而不会出现任何问题,因为没有提交写入操作,因此也不会出现缓存一致性问题。
在多核体系结构中,基本上每个核心都有一个缓存和一个"缓存一致性协议",该协议使某些没有最新信息的核心的缓存无效。我认为大多数处理器实现了MOESI协议以实现缓存一致性。
缓存一致性是一个复杂的主题,已经广泛讨论过(我特别喜欢Joe Duffy的一些文章这里这里)。然而,讨论围绕着代码可能面临的性能惩罚,尽管看起来是无锁的,但由于缓存一致性协议启动以在处理器缓存之间维护一致性,因此可能会减慢速度,但只要没有写入,就没有需要维护的一致性,因此不会影响性能。

仅作澄清,正如评论中所说,由于x86和x64架构实现单总线,因此无法同时访问RAM,而SMP保证了公平访问主内存。尽管如此,每个核心缓存都隐藏了这种情况,使得每个核心都可以拥有自己的数据副本。对于1MB的数据,当核心更新其缓存时可能会导致一些竞争,但那是微不足道的。

一些有用的链接:


一般来说,今天的正确答案是:RAM本身不能支持多个并发访问,但这在缓存中被有效地隐藏了。但是,如果多个内核执行非缓存读取,则仍需要对这些请求进行仲裁。 - MSalters

8
不仅不同的核心允许从同一块内存中读取,而且它们也可以同时写入。但是,这是否“安全”是完全不同的故事。您需要在代码中实现某种保护(通常使用信号量或其衍生物)来防止多个核心争夺同一块内存,以一种您不特别允许的方式。
关于每次核心读取的内存大小,通常是一个寄存器的值,在32位CPU上为32位,在64位CPU上为64位等。即使是流式传输也是逐个字进行的(例如,查看memcpy)。
关于并发多核心的实际情况,每个核心都使用单个总线读写内存,因此访问任何资源(RAM、外部设备、浮点处理单元)都是一个请求一次,一个核心一次。但是,核心内部的实际处理是完全并发的。DMA传输也不会阻塞总线,同时传输会排队,逐个进行处理(我相信,对此不是100%确定)。
编辑:只是为了澄清,与其他回复不同,我只谈论没有缓存的情况。当然,如果缓存该内存,则只读访问是完全并发的。

2
现代处理器中,任何内存访问实际上都有一个缓存行的大小 = 64字节。对缓存行的访问是原子性的。多个核心可以共享读取缓存行。 - osgx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接