第一个示例以 CPU 为中心,不使用 GPU 发起的通信功能。它可以被视为以下章节的基线。CPU 创建可从 CPU 自身管理的接收队列,以接收 GPU 存储器中的数据包,并为每个队列分配流量控制规则。 在运行时,CPU 接收 GPU 存储器中的数据包。它通过 DOCA GPUNetIO 信号量向一个或多个 CUDA 内核通知每个队列新一组数据包的到达,提供 GPU 内存地址和数据包数量等信息。在 GPU 上,CUDA 内核轮询信号量,检测更新并开始处理数据包。 图 5 . GPU 数据包处理管道,CPU 在 GPU 内存中接收数据包,并使用 NVIDIA DOCA GPUNetIO 信号量通知数据包处理 CUDA 内核有关传入数据包 这里,DOCA GPUNetIO 信号量具有类似于 DPDK gpudev communication list 的功能,使得 CPU 接收数据包和 GPU 在处理这些数据包之前等待接收这些数据包之间能够实现低延迟通信机制。信号量还可用于 GPU 在包处理完成时通知 CPU ,或在两个 GPU CUDA 内核之间共享关于已处理包的信息。 该方法可作为性能评估的基准。由于它以 CPU 为中心,因此严重依赖 CPU 型号、功率和内核数量。
GPU 接收和 GPU 处理
上一节中描述的以 CPU 为中心的管线可以通过以 GPU 为中心的方法进行改进,该方法使用 GPU 发起的通信,使用 CUDA 内核管理接收队列。以下部分提供了两个示例:多 CUDA 内核和单 CUDA 内核。
多 CUDA 内核
使用这种方法,至少涉及两个 CUDA 内核,一个专用于接收数据包,另一个专用用于数据包处理。接收器 CUDA 内核可以通过信号量向第二 CUDA 内核提供数据包信息。 图 6 . GPU 数据包处理管线,CPU 在 GPU 内存中接收数据包,并使用 DOCA GPUNetIO 信号量通知数据包处理 CUDA 内核有关传入数据包 这种方法适用于高速网络和延迟敏感的应用程序,因为两个接收操作之间的延迟不会被其他任务延迟。期望将接收器 CUDA 内核的每个 CUDA 块关联到不同的队列,并行地接收来自所有队列的所有数据包。
单 – CUDA 内核
通过使单个 CUDA 内核负责接收和处理数据包,仍然为每个队列专用一个 CUDA 块,可以简化先前的实现。 图 7 . GPU 数据包处理管线,单个 GPU CUDA 内核接收 GPU 内存中的数据包并进行数据包处理 这种方法的一个缺点是每个 CUDA 块两个接收操作之间的延迟。如果数据包处理需要很长时间,应用程序可能无法跟上在高速网络中接收新数据包的速度。
GPU 接收、 GPU 处理和 GPU 发送
到目前为止,大多数关注点都集中在管线的“接收和处理”部分。然而,DOCA GPUNetIO 还可以在 GPU 上生成一些数据,制作数据包并从 CUDA 内核发送,而无需 CPU 干预。图 8 描述了一个完整的接收、处理和发送管线的示例。 图 8 . 具有 GPU CUDA 内核的 GPU 数据包处理管线在 GPU 内存中接收数据包,进行数据包处理,最后制作新数据包