片外memcpy?

时间:2011-08-13 01:36:35

标签: hardware cpu memcpy computer-architecture

我今天在工作中分析了一个执行大量缓冲网络活动的程序,这个程序大部分时间都花在memcpy上,只是在库管理的网络缓冲区和它自己的内部缓冲区之间来回移动数据。 / p>

这让我想到,为什么intel没有“memcpy”指令允许RAM本身(或CPU外存储器硬件)移动数据而不会触及CPU?因为每个单词必须一直带到CPU然后再次推回,当整个事情可以由内存本身异步完成时。

是否有一些架构原因导致这不实用?显然,有时副本将在物理内存和虚拟内存之间,但这些情况下,这些情况随着RAM的成本而逐渐减少。有时处理器最终会等待副本完成,因此它可以使用结果,但肯定不会总是如此。

3 个答案:

答案 0 :(得分:2)

这是一个包含网络堆栈效率的大问题,但我会坚持你的具体指令问题。你建议的是异步非阻塞复制指令,而不是现在使用“rep mov”的同步阻塞memcpy。

一些架构和实际问题:

1)非阻塞内存必须消耗一些物理资源,如复制引擎,其生命周期可能与相应的操作系统进程不同。这对操作系统来说非常讨厌。让我们说线程A在上下文切换到线程B之前就启动了memcpy。线程B也想要做一个memcpy并且比A要高得多。它必须等待线程A的memcpy完成吗?如果A的memcpy长1000GB怎么办?在核心中提供更多的复制引擎会延迟但不能解决问题。基本上,这打破了传统的操作系统时间量和调度。

2)为了像大多数指令一般,任何代码都可以随时发出memcpy insruction,而不考虑其他进程已经完成或将要做什么。核心必须对任何时候在飞行中的异步memcpy操作的数量有一些限制,所以当下一个进程出现时,它的memcpy可能在任意长的积压结束时。 asynch副本缺乏任何确定性,开发人员只会回归旧式同步副本。

3)缓存局部性对性能有一阶影响。已经在L1高速缓存中的缓冲区的传统副本非常快且相对功率效率高,因为至少目标缓冲区保持在核心L1的本地。在网络复制的情况下,在将用户缓冲区交给应用程序之前,就会发生从内核到用户缓冲区的复制。因此,该应用程序享有L1命中和卓越的效率。如果异步memcpy引擎位于核心以外的任何位置,则复制操作会从核心拉出(窥探)线路,从而导致应用程序缓存未命中。净系统效率可能会比现在差很多。

4)asynch memcpy指令必须返回某种标记,该标记用于标识副本以供稍后用于询问副本是否已完成(需要另一条指令)。给定令牌,核心将需要执行某种关于特定挂起或正在进行的复制的复杂上下文查找 - 这些操作由软件比核心微码更好地处理。如果操作系统需要终止进程并清除所有正在进行的和挂起的memcpy操作,该怎么办?操作系统如何知道进程使用该指令的次数以及哪些对应的令牌属于哪个进程?

---编辑---

5)另一个问题:核心外的任何复制引擎都必须在原始复制性能与核心带宽缓存中竞争,这非常高 - 远高于外部存储器带宽。对于缓存未命中,内存子系统会同时瓶颈同步和异步memcpy。对于任何情况,其中至少一些数据在缓存中,这是一个不错的选择,核心将比外部复制引擎更快地完成复制。

答案 1 :(得分:1)

旧PC架构中DMA controller曾支持内存到内存的传输。目前在其他架构中也存在类似的支持(例如TI DaVinci或OMAP处理器)。

问题在于它占用了你的内存带宽,这可能成为许多系统的瓶颈。正如srking的回答所暗示的那样,将数据读入CPU的缓存中,然后将其复制到内存中,可以比内存到内存DMA更高效。即使DMA似乎在后台运行,也会出现与CPU的总线争用。没有免费的午餐。

更好的解决方案是某种zero copy架构,其中缓冲区在应用程序和驱动程序/硬件之间共享。也就是说,传入的网络数据被直接读入预分配的缓冲区,不需要复制,直接将数据从应用程序的缓冲区中读取到网络硬件中。我已经在嵌入式/实时网络堆栈中看到了这一点。

答案 2 :(得分:1)

Net Win?

目前尚不清楚实现异步复制引擎会有所帮助。这样的事情的复杂性会增加开销,可能会抵消这些好处,而且对于那些memcpy()绑定的少数程序来说,这是不值得的。

更重的用户上下文?

实现可能涉及用户上下文或每个核心资源。一个直接的问题是,因为这是一个可能长时间运行的操作,它必须允许中断并自动恢复。

这意味着如果实现是用户上下文的一部分,它表示必须在每个上下文切换上保存的更多状态,它必须覆盖现有状态。

覆盖现有状态正是字符串移动指令的工作原理:它们将参数保存在通用寄存器中。但是如果消耗了现有的状态,那么这个状态在操作期间是没有用的,也可以只使用字符串移动指令,这就是内存复制函数实际工作的方式。

或远程内核资源?

如果它使用某种每核心状态,那么它必须是内核管理的资源。随之而来的环形交叉开销(内核陷阱和返回)非常昂贵,并且会进一步限制利益或将其转化为惩罚。

主意!有那个超级快的CPU的事情吧!

另一种看待这种情况的方法是,已经存在一个高度调整且非常快速的存储器移动引擎,它位于所有那些高速缓存存储器环的中心,必须与移动结果保持一致。那件事:CPU。如果程序需要这样做,那么为什么不将这些快速而复杂的硬件应用于问题呢?