在探测我们的 PCIe 板时,我们发现系统中的所有内容都设置为固定仲裁方案。根据我的阅读,此方案由供应商决定(我假设是我们的操作系统)。
我想尝试一些不同的仲裁方案,看看它对我们的 DMA 利率有何影响。
就上下文而言,我们有一块双插槽主板,上面有 6 个 PCIe 插槽,其中 3 个用于 CPU1,3 个用于 CPU2。我们的一块主板位于一个 CPU 的插槽上,另一块主板位于 CPU2 的插槽上。它们是完全相同的主板,运行着完全相同的软件。我们将数据从系统内存 DMA 传输到位于我们主板上的内存中。两块主板的 DMA 速率各不相同,其中一块主板通常总是比另一块主板快很多。
我们的 PC 供应商证实,其他客户也看到了这种差异,即在不同的 PCIe 插槽上,一块主板似乎比另一块主板具有更高的优先级。
有没有办法利用这个 Port VC Capability Register 来改变仲裁方案?
如果我没有列出调整仲裁方案的正确寄存器,你能告诉我哪个是正确的吗?
答案1
我不认为仲裁是这里的问题,调整它的设置需要主板支持以及内核修改。vc 扩展功能接口在 Linux 内核中部分处理如下:http://lxr.free-electrons.com/source/drivers/pci/vc.c
我曾经在 Linux 中为自定义 PCIe 板编写过驱动程序,并且过去板间路由流量的算法并没有显示出问题,除非您有一个非常不寻常的用例 - 极长的传输,并且具有近乎实时的延迟要求(在这种情况下您不应该使用 PCIe)。
直接影响这种性能并且更容易解决的是总线本身的拓扑结构,尽管这种影响通常几乎无法衡量。
在机器上,运行 lspci 命令:
lspci -tv
这将向您显示 PCIe 接口的树形视图以及它们所采用的 CPU 路径。对于大多数处理器,有些插槽直接连接到 CPU,而其他插槽则通过桥接芯片(请参阅Intel x99 芯片组
这些桥接器会引入延迟,并可能导致吞吐量降低。CPU 直接配置专门用于高性能设备(如视频卡)。回到最初的观点,在处理器微代码深处可能会存在优化,从而进一步降低桥接链路的性能。要更深入地评估 PCIe 插槽的性能和路由,请继续在 sysfs 中操作。
/sys/bus/pci/slots/ 下将列出系统中的 pci 插槽(物理)。其中有一个虚拟文件,将总线地址 <----> 物理插槽关联起来。
/sys/bus/pci/devices 下是所有设备的列表(这是 lspci 获取其信息的地方)。
通过查看每个设备,您可以看到内核公开的所有信息、与它们相关的驱动程序、与设备相关的 CPU(在多 CPU 系统上)等等。
编辑 - 我没有提到一些我认为你已经排除的显而易见的事情,但以防万一:
1. 不同的插槽是否都至少具有与主板一样多的通道?
2. 是否存在规格差异 - 例如主板是 pcie 3,一个插槽是 3,另一个是 2?
3. 除了他们承认之外,您是否与主板供应商和/或驱动程序开发人员讨论过这个问题?他们可能知道一些与此相关的随机勘误表
如果您提供具体的细节,我可以提供具体的建议。
除了查看拓扑结构(速度更快的设备是否在直接 CPU 路径上,而另一个则不是)之外,不知道您使用的芯片组/ CPU 的类型,我只能提供一般性建议,但我将开始关注的三个方面是:
中断延迟:如果主板中断与处理其他中断率较高的设备的 CPU/核心相关联,则性能会受到影响。该核心上是否有其他内核上下文繁重工作?查看 /proc/interrupts 以查看哪些其他内核模块正在使用该 CPU 进行中断处理以及中断发生的计数/速率。尝试在 /proc/irw ... smp_affinity 中调整该设备的 CPU 亲和性。smp affinity 是一个掩码,如果您有 8 个核心并且未指定任何内容,它将被设置为 FF(8 个 1)。如果您将其设置为例如 0x02,这将强制核心 2 处理 IRQ。除非您知道您正在解决特定问题,否则强制进行这些更改很容易使情况变得更糟。
中断支持:查看其中一个设备是否使用 MSI-x 或 MSI 中断,而另一个设备是否使用标准(电气)中断。有时桥接器不支持板卡 MSI 实现(MSI 表示消息信号中断 - 而不是电气中断,它只是通过总线本身发送的数据包)。如果设备通常使用多个中断,但因此只能使用一个中断,除非您直接寻找它,否则很难检测到,并且可能会导致性能问题。
表征性能。内核中有许多工具可以收集性能数据。它们都有一个共同点,那就是记录不全,而且通常不受支持。但话虽如此,我会考虑使用 Ftrace 来表征每个板的 DMA 传输以及每个板的 IRQ 延迟。您可以获得统计信息以及异常事件的具体细节。您可以从这里开始研究:http://elinux.org/Ftrace
一般来说,我强烈反对在非常低级别的设置中进行乱搞,除非尽可能完整地了解你试图纠正的内容(不是要纠正的症状,而是根本原因)。99% 的时间里,你最终会为了它而转动“旋钮”,但不理解为什么或最初的问题是什么,如何评估给定设置的有效性(包括即时和长期稳定性)。
我大量使用 ftrace 进行常规内核调试,并强烈推荐它。如果您希望抽象一点,ftrace 周围有一些包装器,声称可以使其更易于使用,但我发现额外的抽象只会让事情变得更加复杂 - trace-cmd、kernel shark 等。如果您使用的是 Red Hat 系统,您可以查看 systemtap - 虽然不是同一个东西,但可以提供类似的数据(并且它得到了很好的支持)。
答案2
虽然额外的 PCIe 桥接(交换)级别会影响延迟响应和吞吐量,但根据我的经验,由此导致的性能差异并不大。更典型且几乎肯定是您看到的问题是,分配给不同 HBA 卡的用户空间应用程序和/或设备驱动程序内存缓冲区实际上全部分配在两个 CPU 中的一个上,在本例中是 CPU1。因此,连接到 CPU2 的设备发起的所有来自或到内存的 DMA 都比连接到 CPU1 的设备慢,因为所有涉及的系统内存实际上都托管在您的特定工作负载中的 CPU1 上。对于应用程序内存,这是很常见的,您对此无能为力。(对于更高级的应用程序,有些具有基于环境变量或命令行选项的开关,这些开关可以影响它们从何处分配内存,有些应用程序将为不同的进程在不同的 CPU 上分配不同的内存。但这些应用程序很少,大多数不提供这种控制。)
设备驱动程序(假设它在此处由您控制)可以采取措施以 NUMA 感知方式分配其内存,并专门在最靠近 I/O 设备的 CPU 节点上分配驱动程序缓冲区。这需要设备驱动程序中记录的额外步骤,但同样,很少有设备驱动程序会采取这些额外步骤。(有些会)。如果这样做,并且如果(且仅当)设备驱动程序实际将数据从用户复制到内核缓冲区(现在已分配 NUMA),那么您应该会看到两个 HBA 卡在 DMA 方面的性能相同。 (总体交易率可能仍然比其中一个慢,因为对于两个卡中的其中一个,用户空间到内核空间的复制仍然会更慢,因为应用程序的内存(原始复制源)通常全部分配在一个特定的 CPU 节点上(在您的示例中为 CPU1),并且在 CPU2 上从用户空间复制到内核空间所需的时间比在 CPU1 上从用户空间复制到内核空间缓冲区所需的时间更长。所有多插槽系统都会遇到这个问题,但对于某些系统来说,根据它们的 CPU 间互连的速度(如 QuickPath、UPI、Hypertransport)等,这个问题比其他系统更严重。
即使设备驱动程序费尽心思分配节点特定内存,也并不总是有帮助。首先,很多时候,驱动程序可能会直接执行用户空间到设备 DMA(零复制 DMA),而不是先复制到内核空间缓冲区。在这种情况下,没有可以以节点相邻方式分配的关联内核缓冲区。其次,即使设备驱动程序中有节点特定内存,即使设备驱动程序使用该内存,您仍然会看到从用户空间复制到内核空间的差异延迟(近 HBA 到近内核内存的复制速度更快),远 HBA(此处为 CPU2)和远 CPU2 设备内存(如果存在)较慢。在这种情况下,这只是将问题从不平等的 DMA 速度“转移”,改为“不平等”的用户空间到内核空间缓冲区复制。DMA 时间将相等,但事务时间(包括用户到内核的复制)仍然不平衡。后一个原因是许多设备驱动程序编写者不愿意分配节点特定内存的原因之一。 (另一个主要原因是简单的无知。)
无论哪种情况,内存访问速度差异造成的时间损失几乎肯定比 PCIe 交换延迟差异造成的时间损失要大得多。
作为最终用户,您几乎无能为力。作为设备驱动程序编写者,您可以在设备驱动程序中使用 NUMA 感知内存分配技术。根据工作负载,有时这会有很大帮助,有时则毫无作用。
除非您可以让设备驱动程序和源应用程序都以 NUMA 感知方式分配其内存(对于应用程序而言,由于数据分解方式的原因,这通常很困难或不可能),否则您无法解决这种不均匀的速度差异问题。