PCIE的吞吐量如何计算和记忆诀窍?

简介: PCIe标准中的性能参数有好几个,比如设备的带宽和吞吐量是多少?传输速率?

百度百科上,PCIE标准的传输速率与带宽对应表如下(表中速率为单向速率)。网上有些数据是双向的,性能数据就翻倍了。
PCIE 标准概览表

记忆PCIE吞吐量有诀窍

PCIE总线版本为n, 那么 PCIE x8的吞吐量=2的n次方 。 PCIE 3.0 带宽为2^3=8 GB/s ,和表格中7.877大差不差。
其他在x8的吞吐量倍数上折算即可。

详细说明

  1. Width(带宽):通常用x1、x2、x4、x8等表示,表示该链路由几条lane组成。
  2. Speed(速率):通常用2.5GT/s、5GT/s、8GT/s,表示每条lane上的传输速率。PCIe1.0为2.5GT/s,PCIe2.0为5GT/s,PCIe3.0为8GT/s,
  3. GT/s :Giga transation per second (千兆传输/秒),即每一秒内传输的次数。重点在于描述物理层通信协议的速率属性,可以不和链路宽度等关联。
  4. Gbps :Giga Bits Per Second (千兆位/秒)。GT/s 与Gbps 之间其实不是相等的,但可以认为近似相等。近似的原因是编码算法造成的,有极少的码元bit用于存放纠错码了。

PCIe 链路吞吐量计算方法:

  • 吞吐量 = 速率 * 带宽 * 2方向(全双工) * 编码方式

1)PCI-e2.0 协议支持 5.0 GT/s,即每一条Lane 上支持每秒钟内传输 5G个bit;但这并不意味着 PCIe 2.0协议的每一条Lane支持 5Gbps 的速率。因为PCIe 2.0 的物理层协议中使用的是 8b/10b 的编码方式。 即每传输8个bit,需要发送10个bit;这多出的2个bit是纠错码,并不是对上层有实际意义的。

  • 以PCIe 2.0 x8的通道为例,吞吐量=5GT * 8 * 8/10 = 32 Gbps = 4GB/s。

2)PCI-e3.0 协议支持 8.0 GT/s, 即每一条Lane 上支持每秒钟内传输 8G个bit。而PCIe 3.0 的物理层协议中使用的是 128b/130b 的编码方案。 即每传输128个bit,需要发送130个bit。

  • 以PCIe 3.0 x4的通道为例,该链路的吞吐量= 8GT * 4 * 128/130 = 31.508 Gbps = 3.938GB/s
  • 以PCIe 3.0 x8的通道为例,该链路的吞吐量= 8GT * 8 * 128/130 = 63.015Gbps = 7.877 GB/s
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这里提供一个简单的PCIe设备驱动代码样例和注释,请根据自己实际的硬件情况进行修改: ```c #include <linux/module.h> // 模块相关的头文件 #include <linux/pci.h> // PCIe相关的头文件 #include <linux/init.h> // 初始化相关的头文件 // 定义PCIe设备ID static struct pci_device_id pci_ids[] = { { 0x1234, 0x5678, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 0 } }; MODULE_DEVICE_TABLE(pci, pci_ids); // 定义PCIe设备的初始化函数 static int pcie_driver_probe(struct pci_dev *dev, const struct pci_device_id *id) { int err; // 停用设备 pci_disable_device(dev); // 分配设备资源 err = pci_enable_device(dev); if (err) return err; // 映射设备内存 void *hw_addr = pci_iomap(dev, 0, pci_resource_len(dev, 0)); if (!hw_addr) return -EIO; // 打印设备信息 pr_info("PCIe device found (%04x:%04x)\n", dev->vendor, dev->device); // TODO: 对设备进行初始化 return 0; } // 定义PCIe设备的卸载函数 static void pcie_driver_remove(struct pci_dev *dev) { // 解除映射设备内存 pci_iounmap(dev, pci_resource_len(dev, 0)); // 停用设备 pci_disable_device(dev); // 打印设备卸载信息 pr_info("PCIe device removed (%04x:%04x)\n", dev->vendor, dev->device); } // 定义PCIe设备驱动结构体 static struct pci_driver pcie_driver = { .name = "pcie_driver", .id_table = pci_ids, .probe = pcie_driver_probe, .remove = pcie_driver_remove }; // 注册PCIe设备驱动 static int __init pcie_driver_init(void) { return pci_register_driver(&pcie_driver); } // 注销PCIe设备驱动 static void __exit pcie_driver_exit(void) { pci_unregister_driver(&pcie_driver); } // 指定初始化函数和卸载函数 module_init(pcie_driver_init); module_exit(pcie_driver_exit); // 指定模块的信息 MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("PCIe device driver example"); ``` 注释: - `pci_device_id` 结构体用于定义 PCIe 设备的厂商 ID、设备 ID、子系统厂商 ID、子系统 ID 等信息。使用 `MODULE_DEVICE_TABLE(pci, pci_ids)` 宏定义设备 ID 列表,供内核自动匹配设备使用。 - `pcie_driver_probe()` 函数是 PCI 设备驱动的初始化函数,当内核发现匹配的 PCIe 设备时,会调用此函数完成对设备的配置和初始化。在函数中,需要先停用设备,然后为设备分配资源(如内存和 I/O 端口),并将资源地址映射到内核虚拟地址空间。最后,对设备进行初始化,如设置寄存器值、清空中断等。如果初始化失败,需要返回错误码,否则返回 0 表示初始化成功。 - `pcie_driver_remove()` 函数是 PCI 设备驱动的卸载函数。当内核需要卸载 PCIe 设备驱动时,会调用此函数完成对设备的解除映射和停用操作。在函数中,需要先解除内核虚拟地址空间和设备资源的映射,然后停用设备。最后可以打印设备卸载信息(可选)。 - `pci_driver` 结构体用于定义 PCI 设备驱动的名字、设备 ID 列表、初始化函数和卸载函数。使用 `pci_register_driver()` 函数注册 PCI 设备驱动,使用 `pci_unregister_driver()` 函数注销设备驱动。 - `module_init()` 和 `module_exit()` 宏指定初始化函数和卸载函数。`MODULE_LICENSE()` 宏指定此模块的许可证,如 GPL 或 LGPL。其他常用的模块指定宏还包括 `MODULE_AUTHOR()`、`MODULE_DESCRIPTION()` 和 `MODULE_VERSION()`。 - 常用的 PCI 总线相关函数包括 `pci_enable_device()`、`pci_disable_device()`、`pci_resource_start()`、`pci_resource_len()` 和 `pci_iomap()` 等。函数的具体使用方式,请参考相关文档和例程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值