DPDK 系列第一篇: DPDK架构阐述-CSDN博客
DPDK 系列第二篇:CPU Cache详解及DPDK在Cache方面的性能应用-CSDN博客
以如下所示的lscpu 结果 为例,铺垫一些基础概念
[root@cyber ~]# lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 48
On-line CPU(s) list: 0-47
Thread(s) per core: 2
Core(s) per socket: 12
Socket(s): 2
NUMA node(s): 2
Vendor ID: GenuineIntel
CPU family: 6
Model: 85
Model name: Intel(R) Xeon(R) Silver 4214R CPU @ 2.40GHz
Stepping: 7
CPU MHz: 3000.000
CPU max MHz: 3500.0000
CPU min MHz: 1000.0000
BogoMIPS: 4800.00
Virtualization: VT-x
L1d cache: 32K
L1i cache: 32K
L2 cache: 1024K
L3 cache: 16896K
NUMA node0 CPU(s): 0-11,24-35
NUMA node1 CPU(s): 12-23,36-47
NUMA:
Non-Uniform Memory Architecture,非一致性内存架构,与经典计算机系统所有核通过北桥访问内存不同,访问内存所花的时间和处理器相关。之所以和处理器相关是因为该系统每个处理器都有本地内存(Local memory),访问本地内存的时间很短,而访问远程内存(remote memory),即其他处理器的本地内存,需要通过额外的总线
如上lscpu 输出, 系统为numa 架构 ,有两个 node 节点
Socket:
一台物理机的物理CPU的个数,如上lscpu输出,有两个物理cpu
Core:
每个物理cpu上的cpu 核数,如上lscpu 输出,cores per socket 为 12
Threads per core:
每个cpu 和可以裂变(开启超线程)的逻辑cpu 核数 ,如上lscpu 输出, 可以裂变为2
总CPU核数 = 物理CPU个数 X 每颗物理CPU的核数
总逻辑CPU数 = 物理CPU个数 X 每颗物理CPU的核数 X 超线程数
就是一个特定的任务要在某个给定的CPU上尽量长时间地运行而不被迁移到其他处理器上的倾向性。亲和性一词是从affinity翻译来的,实际可以称为CPU绑定。
如我们上一篇 cache 分享所述 (DPDK 系列第二篇:CPU Cache详解及DPDK在Cache方面的性能应用-CSDN博客),在多核运行的机器上,每个CPU本身自己会有缓存,在缓存中存着进程使用的数据,而没有绑定CPU的话,进程可能会被操作系统调度到其他CPU上,就会出现cache 一致性的问题,详细请看上一篇博文。
还有一个重要的原因是 将特定进程进行cpu 绑核以后,再加上 核隔离措施,可以使高性能需求的进程独占 cpu 核,避免其它进程的抢占造成 的 内核陷入 等损耗 。
以上两点在DPDK 的实际应用中都得到了充分的应用。
1、有大量计算要做;
2、测试复杂的应用程序(一些产品声明可以在使用更多硬件时执行得更好。我们不用购买多台机器(为每种处理器配置都购买一台机器),而是可以:①购买一台多处理器的机器,②不断增加分配的处理器,③测量每秒的事务数,④评估结果的可伸缩性);
3、运行时间敏感的、决定性的线程
DPDK通过把线程绑定到逻辑核的方法来避免跨核任务中的切换开销,但对于绑定运行的当前逻辑核,仍然可能会有线程切换的发生,若希望进一步减少其他任务对于某个特定任务的影响,在亲和的基础上更进一步,可以使用核隔离的方式,采取把逻辑核从内核调度系统剥离的方法。
线程独占配置:
如下所示,在 /etc/default/grub 中增加 isolcpus 参数配置,该参数表示要隔离哪些核,可以有两种写法,分别时 isolcpus=0,1,2 核 isolcpus=0-2
执行完上述配置 ,执行更新grub 命令,使配置生效,ubuntu 系统 执行 update-grub 即可生效; centos 或者红帽等系统 根据引导方式执行 grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg 或者 grub2-mkconfig -o /boot/grub2/grub.cfg
DPDK的线程可以作为控制线程,也可以作为数据线程。在DPDK的一些示例中,控制线程一般绑定到MASTER核上(eal_parse_args处理中读到的第一个核为MASTER核),接受用户配置,并传递配置参数给数据线程等;数据线程分布在不同核上处理数据包。 主线程和数据处理线程所在逻辑核在网络处理设备上基本都会进行核隔离处理,保证业务的唯一性。再结合DPDK 的用户态驱动及轮询模式(这块不清楚的,可以参考之前的文章:DPDK 系列第一篇: DPDK架构阐述-CSDN博客),基本可以避免 对应的CPU逻辑核有内核陷入等操作。
如下为 DPDK l3fwd 主流程代码,rte_eal_mp_remote_launch即实现了上边描述的逻辑,调度注册的main_loop 在各逻辑核进行运行,main_loop 中可以根据实际需要,执行同样的代码或者判断不同的核执行不同的逻辑
/* launch per-lcore init on every lcore */
rte_eal_mp_remote_launch(l3fwd_lkp.main_loop, NULL, CALL_MASTER);
RTE_LCORE_FOREACH_SLAVE(lcore_id) {
if (rte_eal_wait_lcore(lcore_id) < 0) {
ret = -1;
break;
}
}
应粉丝要求,使用简单的示例进行linux下核绑定及核隔离的演示
#include
#include
#include
int main()
{
printf("这是一个演示例程\n");
while (1) {
sleep(1);
}
exit(0);
}
1、如上代码,使用gcc 编译生成可执行程序 (gcc -o core_bing core_bing.c)
2、如下所示,可以看到设备有8个cpu ,执行上边生成的示例代码后,执行taskset 工具,可以看到 该进程的 亲和性 MASK 是 0xFF ,即 亲和到 8个核的,并未绑定到单独的核上边
3、使用taskset 将该进程绑定到1核,再次查看,可以看到现在只亲和一核了
4、执行核隔离,将1核单独隔离出去
5、可以看到核隔离后,只有一些内核线程跑在 1核上了
6、重新执行 示例程序,并绑定到1核,可以看到该核上多了我们的示例程序