这是一个包括网络堆栈效率在内的大问题,但我会坚持你对指令的具体问题。您建议的是异步非阻塞复制指令,而不是现在使用“rep mov”可用的同步阻塞 memcpy。
一些架构和实际问题:
1) 非阻塞 memcpy 必须消耗一些物理资源,如复制引擎,其生命周期可能与相应的操作系统进程不同。这对操作系统来说是相当讨厌的。假设线程 A 在上下文切换到线程 B 之前启动了 memcpy。线程 B 也想做一个 memcpy,并且优先级比 A 高得多。它必须等待线程 A 的 memcpy 完成吗?如果 A 的 memcpy 是 1000GB 长怎么办?在核心中提供更多的复制引擎会延迟但不能解决问题。基本上,这打破了传统的操作系统时间量子和调度机制。
2)为了像大多数指令一样通用,任何代码都可以随时发出 memcpy 指令,而不考虑其他进程已经完成或将要做什么。内核在任何时候都必须对运行中的异步 memcpy 操作的数量有一定的限制,因此当下一个进程出现时,它的 memcpy 可能处于任意长的 backlog 的末尾。异步副本缺乏任何确定性,开发人员只会退回到老式的同步副本。
3) 缓存局部性对性能具有一阶影响。已经在 L1 缓存中的缓冲区的传统副本非常快且相对节能,因为至少目标缓冲区仍然位于内核的 L1 本地。在网络复制的情况下,从内核到用户缓冲区的复制发生在将用户缓冲区交给应用程序之前。因此,该应用程序享有 L1 命中率和出色的效率。如果异步 memcpy 引擎存在于核心以外的任何地方,则复制操作会将行从核心中拉出(窥探),从而导致应用程序缓存未命中。净系统效率可能会比今天差得多。
4) asynch memcpy 指令必须返回某种标识副本的令牌,以便稍后使用以询问副本是否完成(需要另一条指令)。给定令牌,核心将需要对特定的待处理或正在运行的副本执行某种复杂的上下文查找——与核心微码相比,这些操作由软件更好地处理。如果操作系统需要终止进程并清除所有正在进行的和挂起的 memcpy 操作怎么办?操作系统如何知道一个进程使用该指令的次数以及哪些相应的令牌属于哪个进程?
- - 编辑 - -
5)另一个问题:核心之外的任何复制引擎都必须与核心的缓存带宽竞争原始复制性能,这非常高——远高于外部内存带宽。对于缓存未命中,内存子系统同样会成为同步和异步 memcpy 的瓶颈。对于至少有一些数据在缓存中的任何情况,这是一个不错的选择,核心将比外部复制引擎更快地完成复制。