DPDK系列之三十一DPDK的并行机制简介

一、并行机制

什么是并行机制?这个很多开发者的眼中,其实是模糊的。可能说起来头头是道,但是细一查究竟,发现都是飘在空中的东西。在前面的“多核和多CPU编程”中,对并行机制已经进行了较深入的分析,这里只简单说明一下。
说起并行(parallelism),就不得不提并发(concurrent)。并发一般是指多线(进)程在一个执行单元上进行轮流执行(时间片),而并行指多线(进)程在多个执行单元上同时执行。大多数开发者一个最明显的谬误往往就在于把并发和并行混淆。当然,有的书籍中,把二者说的不太清楚,甚至从某个角度上有意无意的误导了学习者也是一个重要原因。之所以产生这个现象,一个最重要的原因在于大学课程中的操作系统和计算机原理为了更容易说明进程线程的机制,而简化了很多东西。这样,就导致很多开发者在一开始就把学习的知识想当然的扩展了,这在国外的教科书中就做的比较好(所以搞计算机,教科书尽量用国外的,技术尽量上国外的官网)。
另外一个就是在计算机普及的过程中,并发比并行更简单,实现成本更低。这也导致很多老的开发者,如果技术没有跟进,也会产生这种误解。起初的大型机和小型机上,多CPU的很正常,所以并行编程其实出现的很早。而并发编程,也就是现在开发者理解的多线(进)程(早期的多道程排除出去),其实比并行编程要出现的晚,就一如线程这个概念一样。
对并发和并行的表述很明白,但理解却不是这样简单,没有上面的说的那么清晰明白。因为很多实际的应用程序在现有的机器上执行时,并发和并行是同时存在的。所以可以形象的把并发和并行统一起来,即在应用者的眼中(前端)看来,都是并发,而是否并行,看底层(后端)执行单元(CPU或核心数量)来决定(这会不会是种误导?)。这个有点编译器发展的方向,前后端分离。
其实这也是一个计算机硬件进化的历史,从单核到多核的一个过程。现在主流的计算机,PC端一般是单CPU多核心为主,服务器以多CPU多核心为主。而其它异构的产品如手机等,更是细分了不同的执行和计算单元,从某种程度可以理解成多CPU多核心。而PC端随着GPU编程的发展,CPU和GPU协同工作其实也是一种并行的机制。
故而现在已经无法简单的把并发和并行严格区分出来。当然,实际上,大多数的PC端的应用程序仍然是以并发编程为主,这个是一时半会不会有太大的改变的。
需要注意的是:
上面虽然以多线(进)程为例说明,但一定要记清楚,这是任务分配(前端),到底决定是并行还是并发,还是看执行(后端)是同一执行单元还是多执行单元。另外不要混淆并行和并发混合(M:N:M个线程,N个执行单元,M>N这种情况)。
还有一个说明点,所谓异步和协程(Java21的虚拟线程这些都算)这些都是在以此为基础的另外一种抽象的应用,不要硬夹杂进来。

二、DPDK中的并行

明白了什么是并行机制后,现在看一下DPDK中是如何引入并行机制的。前面在“DPDK系列之五DPDK的线程模型”中已经初步对其进行了一个认识,这里开始进行一个较为全面的分析和介绍。
从宏观上来看,提高执行效率不外乎以下几点:
1、执行(计算等)单元的数量。从简单理论(不考虑竞态)上理解,越多越好(人多好干活嘛)。
2、线(进)程的调度。简单来说,没有调度这种理想状态效率最好(人多更要合理分工)。
3、动态的扩展性。即运行过程中动态的增减来达到效率的最高,否则一个单元执行足以应付,即有九十九个线程闲置也是低效,即达到线性的伸缩(人员需求动态可调配)。
而算法等的完善和优化(提高人员素质),这属于计算机提高效率的细节了或者说具体的业务范畴,这里暂时不做讨论。
在DPDK中应对上面的这些解决方式有:
1、支持多CPU和多核心,并进一步支持以此演进的NUMA。
现代的CPU一般可以有多个安装在一台服务器上,一个CPU上有多个Core,而一个Core又会有多个逻辑核心(超线程技术)。甚至从宏观上看,分布式的系统都可以看做一个大型的计算机,这个扯远了。扯回来,这样,通过多个CPU(含核心),可以最大限度保持非关联的并行度。而多个CPU又进一步衍生出NUMA,保证内存访问的安全和快捷,用来保持内存访问的效率。

2、支持线程亲和性和线程独占,这个有点类似于减少调度(尽量减少线程开销提高Cache命中率)。
多个核心就很容易保持着不相关的线程的并行执行,这其实就是干活的人多了,假如你做为一个包工头,如何保证这些多的人产生出更高的结果?那么最简单的一种办法,如果某个人擅长打字,你就让他专职打字,而不是打一会字就去搬砖。有些人有力气,你非要让他搬一会砖就去打字,除了让这两人感到痛苦,还会直线降低工作效率。这就是CPU的亲和性,这在NUMA的机器上非常重要。同样,亲和性只是让任务偏重于少调度而不是不调度。所以就又有线程独占,也就是绑定到CPU(核心)上,也就是说,这个核心不会再调度,只和绑定的线程快乐的玩耍。
当然,这些是有条件的,如果你的任务需要密集性的计算或者非常复杂和对实时性要求非常高等,才会要求这样做。这和大页内存的限制条件原理是类似的。举个例子,某人擅长打字,但打字的工作一天就一个小时,总不能余下的时间都让他歇着吧?

3、可扩展性
DPDK通过配置等手段可以实现对CPU核心数量的支持来实现计算的可扩展性,同样利用内存的管理实现内存的可扩展性操作,其它也是如此,特别是虚拟化的支持,其实已经从底层更好的支持了可扩展性。

之所以这样做,和整体任务计划中的局部性、减少互斥访问和避免多核调度以及锁的粒度尽量小(或者尽快通过临界区)是密不可分的。但即使如此,在实际的应用中,不可避免的会出现并行的并行控制问题。这其实又重新回到了一个数学概率的问题以及具体到某个场景的数学概率问题。

三、DPDK的应用

在DPDK中,在代码分析中可以知道其通过POSIX库创建线程的方式来Spawn线程并且通过上述的方式来绑定到具体的核心,来实现DPDK的高效率真通信的目标。它分为主从两类,分布在主从核心上。一般控制线程做为主线程,而数据线程做为从线程。
其实DPDK也是针对上面的几个方面进行了实现,只不过在逻辑上划分出来主从,来区分管理和业务,能够更好的满足实际的需求。

四、总结

DPDK的内存机制基本告一段落,那么高效的另外一个重点就是并行。以目前的计算机资源的使用来看,没有一个高效的并行框架基本上是无法达到榨干资源的可能的。就如资本一样,不浪费每一个资源,每一个资源的每一部分,是计算机开发者的终极目标。整体上要推进资源的技术进步,在无法短时间内实现技术进步的前提下,组合应用各种技术把对资源的利用达到极致,这就是计算机技术的宏观的目的。
DPDK就是这其中一个典型的代表,所以,这个并行的机制,就不得直面对待。

你可能感兴趣的:(网络开发,DPDK,网络)