一次只能有一个CPU访问RAM?
我目前正在尝试进入多核编程。我想用C++/Python/Java编写/实现并行矩阵乘法(我猜Java是最简单的)。一次只能有一个CPU访问RAM?
但是我自己无法回答的一个问题是RAM访问如何与多个CPU一起工作。
我的想法
我们有两个矩阵A和B,我们想计算C = A * B:
并行执行只会更快,当N,M或p很大。假设n,m和p> = 10,000。为简单起见,假设n = m = p = 10,000 = 10^4。
我们知道,我们可以计算每个$ {C_ I,J} $ withouth的看着C的其他条目因此,我们可以计算在每一个平行{C_ I,J}:
但是,所有的c_ {1,i}(i \ in 1,...,p)都需要A的第一行。由于A是一个10^8双精度的数组,它需要800 MB。这绝对比CPU缓存大。但是一行(80kB)将适合CPU缓存。所以我想最好把C的每一行都分配给一个CPU(只要CPU是空闲的)。所以这个CPU至少有A在它的缓存中,并从中受益。
我的问题
如何RAM访问了不同的内核管理(在正常英特尔在笔记本)?
我想必须有一个“控制器”,一次给一个CPU独占访问权限。这个控制器有一个特殊的名字吗?
偶然地,两个或多个CPU可能需要相同的信息。他们能同时得到它吗?内存访问是矩阵乘法问题的瓶颈吗?
请让我也知道,当你知道一些好书向你介绍多核编程(在C++/Python/Java中)。
您应该以缓存友好的方式(有很多方法 - 搜索“平铺”here's a nice explanation from Berkeley)分离并行化矩阵乘法的问题,从多核如何共享某些资源(如共享缓存和内存。第一个是指如何避免高速缓存颠簸,并且可以实现数据的有效重用(在给定的高速缓存层次结构上),后者是指内存带宽利用率。确实,两者是连接的,但它们大多是相互排斥的,因为良好的缓存会降低您的出站带宽(这对于性能和功耗来说当然是可取的)。但是,有时候,如果数据不可重复使用或算法无法修改以适应缓存,则无法完成。在这些情况下,内存带宽可能会成为你的瓶颈,不同的核心将尽可能地分享它。大多数现代CPU都有多个共享最后一级缓存的内核(我不确定这是在某些智能手机细分市场中的情况,但通常适用于笔记本电脑/台式机/服务器)。该缓存反过来与内存控制器进行通信(该内存控制器曾经坐落在一个名为北桥的不同芯片上,但是由于几年前已集成到大多数CPU中以便更快访问)。 通过内存控制器,整个CPU可以与DRAM进行通信并告诉它要获取什么。MC通常足够聪明,可以组合访问,从而只需要最少的时间和精力来获取(请记住,从DRAM中获取“页面”是一项长期任务,通常需要首先驱逐缓存在读出放大器中的当前页面)。
请注意,这种结构意味着MC不必分别与多个内核通话,它只是将数据提取到最后一级缓存。内核也不需要直接与内存控制器通信,因为访问通过最后一级缓存进行过滤(有少数例外,例如不可缓存的访问将通过它,IO访问有另一个控制器)。除了它们自己的私有缓存之外,所有内核都将共享该缓存存储。
现在有关共享的说明 - 如果2个(或更多)内核同时需要相同的数据,那么您很幸运 - 无论它是否已经在缓存中(在这种情况下,两个访问都将通过发送数据发送到每个核心,并将它们标记为“共享”),或者如果数据不存在,则两者都将等到MC能够将其带入(一次),然后继续与打击情况一样。然而,一旦有一个或多个内核需要将新数据写入该行或其中的一部分,一旦出现异常。在这种情况下,修改器将发出读取所有权请求(RFO),这会阻止共享线路并使其他核心中的所有副本无效,否则您将面临失去缓存一致性或一致性的风险(因为一个核心可能使用陈旧的数据或察觉不正确的记忆顺序)。这被称为并行算法中的争用条件,并且是复杂的锁定/屏蔽机制的原因。再次注意,这与实际的RAM访问是正交的,并且可能同样适用于最后一级缓存访问。
您可能还想了解[cache coherence](http://en.wikipedia.org/wiki/Cache_coherence)。 –
多核和多CPU之间还有一个区别(从内存管理角度看),因为同一物理CPU上的多个内核将共享(至少一些)高速缓存。所有内核都可以从RAM中读取,尽管它不能“同步”。它们具有多个内核的典型现代CPU将在所有内核中实现共享的高级缓存。 – Leigh
为什么要发明轮子? :)为什么不采取像OpenBLAS这样的东西,并看看实施? –