多核系统中的CPU优化技术

2018-11-26 07:37杜秀芳
商情 2018年46期

杜秀芳

【摘要】本文主要介绍了在多核系统中从软件上开发的一种CPU优化技术。这种优化技术针对CPU使用不均衡的问题,利用任务调度算法能自动平衡CPU的使用,提高多核系统中CPU的使用率,从而发挥CPU的性能优势。

【关键词】多核系统 CPU优化 任务调度

0 引言

随着CPU技术的发展,CPU性能的提高方向已经从单核CPU频率的提高往CPU核数的提高转变。以INTEL至强系列为例,Xeon D-1521是四核CPU,每核的主频是2.4GHz;Xeon D-1531处理器是6核设备,主频是2.2GHz,Xeon E5 v4处理器是10核心设备,主频是2.2GHzo这三款处理器都是采用14nm工艺制造,主频并没有太大分别,在跑分上分别为6980、9730、13923。但是,CPU技术提高了,应用技术并没有很好的配合提高,并不能发挥CPU的性能优势。本文开发了一种CPU优化技术,可以提高多核系统中CPU的使用率。

1 CPU使用的不均衡问题

在CPU技术的发展过程中,核心数量的增长是近年的趋势,对于多核支撑,需要程序开发人员自行分配核心的工作量。但这件事并不是一个简单的工作,所谓“一核有难十核围观”。虽然后来的技术有一定的改善,但是还是没有实现均衡的使用。

2 绑核的任务系统

本文开发了一套任务调度框架,在本程序框架下运行的程序,会自动平衡多核CPU的使用,达到较优的多核使用效率。本框架是在linux环境下开发和调试的,代码使用C语言。

2.1 action的定义

本框架把每一个要完成的任务定义为一个action。一个action,从业务上是一个软件要处理的事务单元,也可以多个事务单元完成一个事务;从代码上任务可以理解为函数。以路由器为例,从业务上,它处理的任务都是I/O相关的内容,所以每个任务包含I/O相关的信息,比如I/O请求等等;从代码上,用一个函数指针来描述任务。由于我们这个任务调度算法设计的初衷是方便任务调度、提高CPU使用的效率。所以要求任务的处理时间不能太长。这个太长在CPU领域里面定位为100ms,这个是个估计值。任务的处理时间短是任务的内在要求。

当任务的时间过长,会损耗框架的灵活调度。所以当一个任务的处理时间可能比较长的时候,需要拆分成多个任务,这就是任务拆分。任务拆分的目的是控制单个任务的处理时间。

2.2 线程和CPU的关系

对于高性能处理器,往往有多个CPU,为了讲清楚这个关系,我们假设CPU的核数是6核。

在操作系统层面上,基本的运行单元是进程,进程中的调度单元是线程。一个进程可以有多个线程,但是至少要有一个线程,否则就没必要存在。对于进程所拥有的资源,线程也是可以共享的。在有了线程的操作系统中,进程是分配资源的基本单元,而线程是独立运行和独立调度的基本单元。相比较进程来讲,线程更小,而且不拥有系统资源,所以对线程的调度开销会小得多,通过调度线程可以提高系统的多个程序并发执行的程度。

在配置过程中,一个CPU可以绑定多个线程,即多个线程公用一个CPU。每个线程绑定一个CPU时,系统的性能较高。所以在主程序启动之初,需要把每个线程跟CPU分别绑定。

2.3 CPU的线程的动卜态补偿

为了适应程序开发的多样性,这里任务也分为两种:一种任务是独立的,即这种任务可以独立的运行在一个线程上,不依赖其他的任务,可以独立完成;另一种任务是非独立的,即任务之间有相关性,根据这个要求,这类任务需要运行在同样的线程上,以避免共享资源的访问导致性能下降。独立的任务跟所在的线程无关,可以运行在任何的线程上;非独立的任务只能运行在同一个线程上。通常来说,对于大多数程序开发,独立的任务占大多数。

对于非独立的任务,任务的分配机制是固定的,由使用者自行指定线程(也就是固定线程)。

对于独立的任务,根据线程(CPU)的忙碌程度,把任务分配到不太忙碌的线程,实现CPU的均衡配置,这就是任务迁移。

2.4 技术关键点

实现上,首先要设置进程的CPU数量,也就是该程序所在进程使用多少个CPU。这里采用的接口是CPU亲和度接口族,主要是这几个接口。

#define_GNU_SOURCE/关See feature_test_macros(7)*/

int sched_setaffinity(pid_t pid,size_t epusetsize,cpu_set_t*mask);

int sched_getaffinity(pid_t pid,size_t cpusetsize,cpu_set_t*mask);

其中,pid是要CPU的进程pid;mask是二进制掩码,比如0x000F表示使用CPUO、CPU1、CPU2、CPU3;0x00F1表示使用CPU0、CPU4、CPU5、CPU6、CPU7。

第二个技术点是要设置线程的CPU关系,这一点在实现上需要使用线程CPU绑定函数,这里面

int pthread_setaffinity_np(pthread_t thread,size_t epusetsize,const cpu_set_t*cpuset);

int pthread-getaffinity-np(pthread_t thread,size_t cpusetsize,cpu_set_t*cpuset);

其中,thread為线程id; cpusetsize为cpu数组大小,固定填sizeof(cpu_set_t);cpuset是一个集合,角来表示设置哪些CPU跟这个线程绑定。

这个集合需要提前创建,使用CPU_SEI,接口实现添加。例如:

CPU ZERO(&cpuset;);

for(j=0;i<8;j++)

CPU_SET(j,&cpuset;);

这一段代码的意思是设置一个CPU包含CPU0-CPU7的集合。

另一个关键点就是要求编程人员能够对任务进行划分,划分成尽量与线程无关的任务块,这样才能实现任务的自由切换。

3 结束语

CPU技术的发展日新月异,CPU软件技术的发展也是在逐步提高,逐步发挥出硬件的优势,本文提供了一种在多核设备上从软件上优化CPU的技术方案。希望能带给大家一点思路。

参考文献:

[1]郭建伟.灵活调度,激活多核CPU“潜力”[J].电脑知识与技术(经验技巧),2017(11):33-34.