Memory 从PCIe内存到Memcpy的时间比从Memcpy到PCIe内存的时间要长

Memory 从PCIe内存到Memcpy的时间比从Memcpy到PCIe内存的时间要长,memory,linux-kernel,linux-device-driver,pci-e,Memory,Linux Kernel,Linux Device Driver,Pci E,我正在尝试从PCIe 2.0(2通道)设备向Linux PC读/写数据。用于读取和写入的内存位于PCIe设备中的不同RAM位置。这些内存使用ioremap映射到Linux-PC中。我的用例是实现每秒18MBytes的读/写吞吐量,这显然是PCIe链路所支持的。PCIe设备上的内存未缓存 我能够实现写入吞吐量,即当我使用memcpy从Linux PC本地内存写入PCIe设备内存时。在这种情况下,memcpy处理9216字节数据的时间不到1毫秒。但当我将ioremapped PCIe内存读取到Lin

我正在尝试从PCIe 2.0(2通道)设备向Linux PC读/写数据。用于读取和写入的内存位于PCIe设备中的不同RAM位置。这些内存使用ioremap映射到Linux-PC中。我的用例是实现每秒18MBytes的读/写吞吐量,这显然是PCIe链路所支持的。PCIe设备上的内存未缓存

我能够实现写入吞吐量,即当我使用memcpy从Linux PC本地内存写入PCIe设备内存时。在这种情况下,memcpy处理9216字节数据的时间不到1毫秒。但当我将ioremapped PCIe内存读取到Linux本地内存时,数据丢失正在发生。我分析了memcpy,它需要1毫秒以上的时间,有时9216字节的数据需要2毫秒。我不想为此操作执行DMA


你有没有想过在这种情况下会出现什么问题?我该怎么处理呢?

这完全是意料之中的事,对此你无能为力。CPU只能发出串行字大小的读写,由于协议开销,PCIe链路的吞吐量非常低。每个操作都有24或28字节的相关开销-即12或16字节的TLP报头加上12字节的链路层开销,CPU一次只能操作4或8个字节…在最佳情况下效率为25%(8/(8+24)=25%),在最坏情况下效率为12.5%(4/(4+28)=12.5%)

然而,协议开销并不是唯一的问题。PCIe中的写操作被发布,因此CPU可以简单地发出一系列背靠背写操作,这些写操作最终进入总线和设备。另一方面,在读取时,CPU只能发出一次读取操作,等待它遍历总线两次,存储结果,发出另一次读取,等等。由于它一次只能操作8个字节,由于PCIe总线上的延迟相对较高(每次传输可以达到微秒级),因此性能非常糟糕


解决方案是什么?使用DMA。PCIe专门设计用于支持总线上的高效DMA操作,因为设备可以执行更大的读写操作,每次操作的最小值可达128字节。

首先发布一些代码。这就是未缓存传输的结果。写入速度更快,因为它们可以被缓冲。另一方面,读取可以保证以前的所有写入都在总线上完成。这也可能会影响吞吐量。@CL。谢谢您的回复。内存在PCIe设备端取消缓存,而不是在Linux PC端。PCIe设备内存缓冲区正以正确的速率变满。从PCIe内存到缓存的Linux PC本地内存的memcpy需要更多时间。我不明白您所说的写入速度更快。如果源、目标和字节计数是32位对齐的,您可以使用
\uuuuuuuuuWrite32\uCopy
\uuuuuuuuiRead32\uCopy
(记住将字节计数除以4)而不是
memcpy
。如果源、目标和字节计数是64位对齐的,则可以使用
\uuuuu iowrite64\u copy
\uuuuuu ioread64\u copy
(记住将字节计数除以8)。