我们能否使用SSE指令集来写入内存映射的PCI设备内存?

3
我有一个使用情况,其中x86 CPU必须将64个字节的数据写入已经映射到用户空间的PCIe从设备的内存中。目前,我使用memcpy来完成这项工作,但结果证明它非常慢。我们可以使用Intel SSE intrinsics(例如_mm_stream_si128)来加速吗?或者除了使用DMA之外,还有其他机制可以使用吗?
目标是将所有64个字节打包成一个TLP,并在PCI总线上发送,以减少开销。

你确定你的memcpy()实现没有使用SSE指令吗? - Jason R
memcpy来自于标准的glibc库,因此我有点怀疑它是否使用SSE指令。 - Anil Abraham
多慢才算慢?使用或不使用SSE按几个周期的顺序复制数据。 - user3528438
1
@AnilAbraham:通过在调试器中运行代码并进入memcpy(),或者通过反汇编C库文件来检查。你会发现memcpy()通常在你的平台上被很好地优化了,因为它经常被使用。 - Jason R
1个回答

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%的机会可能没有区别。

流式存储到MMIO区域可能避免CPU在上一个写操作的clflush之后进行读取以获取所有权。 clwb尚不可用,因此唯一的选择是使用clflush,它会将数据从缓存中逐出


非时序加载/存储被称为弱排序。不确定是否需要更多的栅栏来保证顺序。
流式加载/存储的一个用例是从不可缓存的内存(如视频RAM)复制。我不确定是否可以将其用于MMIO。我找到了一篇关于此的文章,讨论如何从MMIO中读取而不仅仅获取相同的缓存值。

更新:对于写结合(write-combining)的MMIO区域,确保使用NT存储器;否则,对于UC存储器,使用越宽的向量越好。(在内核驱动程序中,保存/恢复FPU状态以便使用SSE/AVX可能或可能不值得一试。) - Peter Cordes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接