多线程和内存

lin*_*s77 6 c++ cpu multithreading x86-64

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

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

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

Jor*_*oba 10

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

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

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

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

一些有用的链接:


Bli*_*ndy 5

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

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

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

编辑:只是为了澄清,不像这里的其他回复,我只谈论一个无缓存的情况.当然,如果内存被缓存,则只读访问是完全并发的.

  • 对于现代处理器,任何内存访问实际上都有一个缓存行大小 = 64 字节。对缓存行的访问是原子的。内核可以共享行以进行读取。 (2认同)