DPDK多线程初步解析

本文介绍了DPDK的高性能特性,一个处理器核每秒能处理约33M个报文,平均处理时间约80个时钟周期。DPDK通过CPU亲和绑定和多线程技术避免线程调度导致的性能下降。文章详细讲解了DPDK中lcore的初始化、注册过程以及在多核上的运行机制,并以hello world程序为例展示了多线程的使用。
摘要由CSDN通过智能技术生成

上一篇文章中谈到DPDK是一个高性能的用户态驱动,改变了网卡驱动原先的中断为轮询的模式,那么它的性能到底有多强,用数据来说明吧。

1. DPDK性能有多强

DPDK的一个处理器核每秒可以处理约33M个报文,大概30纳秒处理一个报文,在处理器频率2.7GHz的情况下,处理一个数据报文需要80个时钟周期。

在传统的方法上,一个数据报文到达网口后,会经历如下过程:

  1. 写接受描述符到内存,填充数据缓冲区指针,网卡接收到报文后就根据该地址把报文内容填进去。
  2. 从内存中读取接收描述符(到接收到报文时,网卡会更新该结构),从而确认是否收到报文。
  3. 从接收描述符确认收到报文时,从内存中读取控制结构体的指针,再从内存中读取控制结构体,把从接收描述符中读取的信息填充到该控制结构体。
  4. 更新接收队列寄存器,表示软件接收到了新的报文。
  5. 从内存读取报文头部,决定转发端口。
  6. 从控制结构体把报文信息填入到发送队列发送描述符中,更新发送队列寄存器。
  7. 从内存中读取发送描述符,检查是否有包被硬件发送出去。
  8. 如果有的话,则从内存中读取相应控制结构体,释放数据缓冲区。

在这8个步骤中,有6次内存读,而处理器从一级cache读需要3-5时钟周期,二级是十几个时钟周期,三级是几十个时钟周期,而从内存读取数据,由于收到NUMA架构(可以理解为,内存也分给了不同的核,每个核访问自己的内存特别快,访问别的核的内存则需要很长时间)的影响,尤其是不在一个Socket的核之间的内存读取,会花费很长时间,所以平均访问内存需要的时钟周期大约是几百个。处理一个报文80个时钟周期,就要求数据在cache中,而且一旦不命中,性能会严重下降。

而在操作系统中,最容易造成性能下降的是线程的调度,尤其是核间线程的切换,最容易造成cache miss和cache write back。所以在DPDK中利用的是线程的CPU亲和绑定的方式,来指定任务到不同的核上。再进一步,可以限制一些核不参与Linux的系统调度,这样就可以达到任务独占的目的,最大限度地避免了cache不命中带来的性能下降。

查阅DPDK资料,发现DPDK中的多线程是基于linux系统里的pthread实现的,lcore指的是EAL线程,并且在命令行参数中使用“-c”带十六进制参数作为coremask,该掩码的意义是为二进制数上为1的一位即表示将要绑定独占的线程,例如:掩码是16进制的f,二进制对应为1111,即表示cpu0、cpu1、cpu2、cpu3作为逻辑核为程序所用。

2. lcore的初始化如下:
  1. rte_eal_cpu_init()函数中,通过读取/sys/devices/system/cpu/cpuX/下的相关信息,确定当前系统有哪些核,以及分别属于哪些socket(这里的socket是NUMA架构中socket,不是网络中的套接字)。
  2. eal_parse_args()函数,解析-c参数,确认哪些核是可以用的,并且设置第一个核为MASTER。
  3. 为每一个SLAVE核创建线程,并调用eal_thread_set_affinity()绑定CPU,每个线程的执行的其实是一个主体是while死循环的调用不同模块注册到lcore_config[lcore_id].f的回调函数eal_thread_loop()。

*注:在eal_thread_loop()中,将线程绑定核,然后置于了等待的状态。绑定核函数基于linux原型函数f_pthread_setaffinity_np,在pthread_shim.c中有对各种pthread函数封装的实现。

3. lcore的注册:
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值