【问题标题】:Can we use SSE intrinsics to write to a memory mapped PCI device memory我们可以使用 SSE 内部函数写入内存映射的 PCI 设备内存吗
【发布时间】:2015-08-27 12:00:17
【问题描述】:

我有一个用例,其中 x86 CPU 必须将 64 字节的数据写入 PCIe 从设备,其内存已被 mmapp'ed 到用户空间。截至目前,我使用 memcpy 来做到这一点,但事实证明它非常慢。我们可以使用像 _mm_stream_si128 这样的英特尔 SSE 内在函数来加速它吗?或使用 DMA 以外的任何其他机制。

目标是将所有 64 字节打包到一个 TLP 中,并在 PCI 总线上发送以减少开销。

【问题讨论】:

  • 您确定您的 memcpy() 实现尚未使用 SSE 指令吗?
  • memcpy 来自标准 glibc,所以我有点怀疑是否使用 SSE 指令。
  • 慢有多慢?有或没有 SSE 以几个周期的顺序复制数据。
  • @AnilAbraham:通过在调试器中运行代码并进入memcpy() 或通过反汇编 C 库文件来检查。您会发现 memcpy() 通常针对您的平台进行了很好的优化,因为它被频繁使用,所以应该如此。

标签: sse mmap pci


【解决方案1】:

据我了解,内存映射 I/O 不会使某些存储指令特别。 movq mem, xmm的8B店铺与mov mem, r64的店铺相同。

我认为如果你有 64B 写入 MMIO,你应该使用任何指令在生成时最有效地执行它,然后刷新缓存行。生成一个 64B 缓冲区然后执行 memcpy(或者自己使用四个 movdqa 或两个 AVX vmovdqa)是浪费时间,除非您希望生成 64B 的代码很慢并且更有可能比 memcpy 中途中断。如果您处于无法禁用中断的用户空间中,则计时器中断可以随时出现,包括在您的 memcpy 期间。由于您不能保证完整的 64B 写入,因此 99.99% 的机会写入完整的高速缓存行与 99.99999% 的机会概率。不会有什么不同。

Streaming stores 到 MMIO 区域可能会避免 CPU 在上次写入的 clflush 之后执行读取所有权。 clwb isn't available yet, so the only option is clflush, which evicts the data from cache.


非临时加载/存储是所谓的弱排序。 IDK 如果这意味着您需要更多的围栏来保证订购。

流式加载/存储的一个用例是copying from uncacheable memory, like video RAM。我不确定是否将它们用于 MMIO。我找到了this article about it,在谈论如何从 MMIO 读取而不只是获得相同的缓存值。

【讨论】:

  • 更新:是的,如果 MMIO 区域是 WC 而不是不可缓存,您确实希望确保使用 NT 存储进行写入组合。否则对于 UC 内存,您使用的向量越宽越好。 (保存/恢复 FPU 状态可能值得也可能不值得,以便您可以在内核驱动程序中使用 SSE/AVX。)
猜你喜欢
  • 2011-12-22
  • 2019-11-21
  • 1970-01-01
  • 1970-01-01
  • 2010-12-10
  • 1970-01-01
  • 2016-05-05
  • 2016-02-23
  • 1970-01-01
相关资源
最近更新 更多