DPDK多线程:EAL pthread和lcore Affinity(F 您所在的位置:网站首页 dpdk线程 DPDK多线程:EAL pthread和lcore Affinity(F

DPDK多线程:EAL pthread和lcore Affinity(F

2023-12-12 03:29| 来源: 网络整理| 查看: 265

多线程

DPDK通常每个内核固定一个pthread,以避免任务切换的开销。这可以显着提高性能,但缺乏灵活性,而且并不总是有效的。

电源管理通过限制CPU运行时间来帮助提高CPU效率。但是,也可以利用可用的空闲周期来利用CPU的全部功能。

通过利用cgroup,可以简单地分配CPU利用率配额。这提供了另一种提高CPU效率的方法,但是有一个先决条件。DPDK必须处理每个内核在多个pthread之间的上下文切换。

为了获得更大的灵活性,不仅将pthread亲和性设置给CPU,而且还设置给CPU集是很有用的。

EAL pthread和lcore Affinity

术语“ lcore”是指EAL线程,它实际上是Linux / FreeBSD pthread。“ EAL pthreads”由EAL创建和管理,并执行remote_launch发出的任务。在每个EAL pthread中,都有一个称为_lcore_id的TLS(线程本地存储)用于唯一标识。由于EAL pthread通常将1:1绑定到物理CPU,因此_lcore_id通常等于CPU ID。

但是,当使用多个pthread时,在EAL pthread和指定的物理CPU之间的绑定不再总是1:1。EAL pthread可能与CPU集有关联,因此_lcore_id将与CPU ID不同。因此,定义了一个EAL长选项'–lcores'来分配lcores的CPU关联性。对于指定的lcore ID或ID组,该选项允许设置该EAL pthread的CPU集。

格式模式:

–lcores =' [@ cpu_set] [, [@ cpu_set],...]'

“ lcore_set”和“ cpu_set”可以是单个数字,范围或组。

数字是“数字([0-9] +)”;范围是“ -”;组是“( [,,...])”。

如果未提供“ @cpu_set”值,则“ cpu_set”的值将默认为“ lcore_set”的值。

例如,“-lcores ='1,2 @(5-7),(3-5)@(0,2),(0,6),7-8'”表示开始9个EAL线程; lcore 0在cpuset 0x41(cpu 0,6)上运行; lcore 1在cpuset 0x2(cpu 1)上运行; lcore 2在cpuset 0xe0(cpu 5,6,7)上运行; lcore 3,4,5在cpuset 0x5(cpu 0,2)上运行; lcore 6在cpuset 0x41(cpu 0,6)上运行; lcore 7在cpuset 0x80(cpu 7)上运行; lcore 8在cpuset 0x100(cpu 8)上运行。

使用此选项,可以为每个给定的lcore ID分配关联的CPU。它也与corelist('-l')选项的模式兼容。

非EAL pthread支持

可以将DPDK执行上下文与任何用户pthread(也称为非EAL pthread)一起使用。有两种非EAL pthread:

通过调用成功分配了具有有效_lcore_id的已注册非EAL pthread,该有效_lcore_id已成功分配rte_thread_register(),具有LCORE_ID_ANY的未注册非EAL pthread,

对于未注册的非EAL pthread(具有LCORE_ID_ANY _lcore_id),某些库将使用替代的唯一ID(例如TID),一些库将完全不受影响,某些库将起作用,但有局限性(例如计时器和内存池)。

所有这些影响都在“ 已知问题”部分中提到。

公共线程API

有两个公共API rte_thread_set_affinity(),它们rte_thread_get_affinity()是针对线程引入的。在任何pthread上下文中使用它们时,将设置/获取线程本地存储(TLS)。

这些TLS包括_cpuset和_socket_id:

_cpuset存储与pthread相关的CPU位图。_socket_id存储CPU集的NUMA节点。如果CPU集中的CPU属于不同的NUMA节点,则_socket_id将设置为SOCKET_ID_ANY。 控制线程API

可以使用公共API创建控制线程 rte_ctrl_thread_create()。这些线程可以用于管理/基础架构任务,并且可以由DPDK在内部使用,以实现多进程支持和中断处理。

这些线程将在原始进程CPU亲缘关系的CPU上进行调度,从中排除数据平面和服务内核。

例如,在8个CPU的系统上,使用-l 2,3(数据平面核心)启动dpdk应用程序,然后根据可通过任务集(Linux)或cpuset(FreeBSD)等工具控制的相似性配置,

没有亲和力配置,控制线程将最终出现在0-1,4-7个CPU上。如果关联性限制为2-4,则控制线程最终将在CPU 4上结束。如果将关联性限制为2-3,则控制线程将最终在CPU 2(主lcore,这是没有CPU的情况下的默认值)上。 已知的问题

rte_mempool

rte_mempool使用内存池中的每个内核缓存。对于未注册的非EAL pthread,rte_lcore_id()将不会返回有效数字。因此,目前,当rte_mempool与未注册的非EAL pthread一起使用时,put / get操作将绕过默认的mempool缓存,并且由于这种绕过而导致性能下降。在未注册的非EAL上下文中,只有用户拥有的外部缓存才能与显式缓存参数一起使用rte_mempool_generic_put()并rte_mempool_generic_get()接受该参数。

rte_ring

rte_ring支持多生产者入队和多消费者出队。但是,它是非抢占式的,具有使rte_mempool不可抢占的效果。

注意

“非抢占式”约束是指:

在给定的环上执行多生产者排队的pthread不能被在同一环上进行多生产者排队的另一个pthread抢占。在给定环上执行多消费者出队的pthread不能被在同一环上进行多消费者出队的另一个pthread抢占。

绕过此约束可能导致第二个pthread旋转,直到再次调度第一个。此外,如果第一个pthread被具有更高优先级的上下文抢占,则甚至可能导致死锁。

这意味着,涉及可抢占pthread的用例应考虑谨慎使用rte_ring。

它可以用于可抢占的单一生产者和单一消费者用例。它可以用于不可抢占的多生产者和可抢占的单消费者用例。它可以用于可抢占的单生产者和不可抢占的多消费者用例。它可以由其调度策略全部为SCHED_OTHER(cfs),SCHED_IDLE或SCHED_BATCH的可抢占的多生产者和/或可抢占的多消费者pthread使用。用户应在使用前注意性能下降。调度策略为SCHED_FIFO或SCHED_RR的多生产者/消费者pthread务必不要使用它。

另外,应用程序可以使用无锁堆栈内存池处理程序。在考虑此处理程序时,请注意:

它目前仅限于aarch64和x86_64平台,因为它使用的指令(16字节比较和交换)在其他平台上尚不可用。与非抢占式rte_ring相比,它的平均情况性能较差,但是软件缓存(例如,内存池缓存)可以通过减少堆栈访问次数来缓解这种情况。

rte_timer

rte_timer_manage()不允许在未注册的非EAL pthread上运行 。但是,允许从非EAL pthread重置/停止计时器。

rte_log

在未注册的非EAL pthread中,没有每个线程的日志级别和日志类型,而是使用全局日志级别。

杂项

未注册的非EAL pthread不支持rte_ring,rte_mempool和rte_timer的调试统计信息。

cgroup控件

以下是cgroup控件用法的简单示例,有两个pthreads(t0和t1)在同一个内核($ CPU)上执行数据包I / O。我们预计只有50%的CPU花费在数据包IO上。

mkdir / sys / fs / cgroup / cpu / pkt_io mkdir / sys / fs / cgroup / cpuset / pkt_io echo $ cpu> /sys/fs/cgroup/cpuset/cpuset.cpus echo $ t0> / sys / fs / cgroup / cpu / pkt_io / tasks echo $ t0> / sys / fs / cgroup / cpuset / pkt_io / tasks echo $ t1> / sys / fs / cgroup / cpu / pkt_io / tasks echo $ t1> / sys / fs / cgroup / cpuset / pkt_io / tasks cd / sys / fs / cgroup / cpu / pkt_io 回声100000> pkt_io / cpu.cfs_period_us 回声50000> pkt_io / cpu.cfs_quota_us


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有