【问题标题】:Memcpy from PCIe memory takes more time than memcpy to PCIe memory从 PCIe 内存的 Memcpy 比从 PCIe 内存的 memcpy 花费更多的时间
【发布时间】:2017-01-31 13:59:28
【问题描述】:

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

我能够实现写入吞吐量,即当我使用 memcpy 从 Linux PC 本地内存写入 PCIe 设备内存时。在这种情况下,对于 9216 字节的数据,memcpy 花费的时间不到 1 毫秒。但是当我将 ioremap 的 PCIe 内存读取到 Linux 本地内存时,数据丢失正在发生。我分析了 memcpy,9216 字节的数据需要超过 1 毫秒,有时需要 2 毫秒。我不想为这个操作做 DMA。

对这种情况下可能出现的问题有什么想法吗?我该如何处理?

【问题讨论】:

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

标签: memory linux-kernel linux-device-driver pci-e


【解决方案1】:

这完全在意料之中,对此您无能为力。 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 字节。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-27
    • 2019-03-28
    • 2020-07-24
    • 2013-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多