采用多核处理器芯片构成计算机系统一个片内多处理器的并行计算机系统。种并行计算机系统过去只出现超级计算中心和集群计算机系统中。现在,随着处理器芯片进入多核时代,使得千家万户的计算机系统都成为多处理器的并行计算机系统。这种并行计算机系统是一种并行进程和并行线程的系统,多个进程和线程可以真正地并行运行,而不是像在单处理器系统中那样轮流地在CPU上运行。但是在多核系统中,原有的单个程序的运行速度并不能得到提高。要提高单个程序的运行性能,需要重新设计原有程序,将单个计算任务分解成多个并行的子任务,让这些子任务分别在不同的处理器核上运行。这样,需要采用不同的程序设计手段。随着多核时代的到来,并行程序设计将成为软件行业的必备知识和技能。
多核与程序设计
与单处理器系统不同,运行在多处理器系统中的程序是多线程的程序。这种程序必须是可重入的,即程序代码能够被重叠地启动并且同时运行在多个上下文中控制工程网版权所有,这些运行上下文构成多个线程。代码的可重入意味着在多次进入同一段代码的线程之间避免竞态(race condition)现象。竞态现象发生在对资源的共享访问情况下。当两个运行的线程需要访问相同的
数据竞争出现在两个数据相关的线程之间。这时,线程的运行结果与线程的运行顺序有关。例如,对于以下两个线程:
// 线程1
t = x;
x = t + 1;
// 线程2
u = x;
x = u + 2;
两个线程的并行运行情况有以下三种可能,导致三种不同的结果,使得x的分别为1、2和3CONTROL ENGINEERING China版权所有,如表1所示。解决这个问题需要采用同步机制和互斥机制。同步机制是并行系统中保持各并行程序正确运行的必要的控制机制。它用于在并行的线程之间进行时间上的协调。互斥机制则是实现同步机制的基础。在单处理器系统中www.cechina.cn,这种机制可以建立在存储器变量的基础上。在单处理器系统中www.cechina.cn,线程的访存操作本身就是一种互斥的机制。而在多核系统中,这种机制需要通过存储器一致性机制和现成通信机制来实现。
并行程序的概念
多处理器系统并行程序设计中需要进行任务划分、数据划分和数据流划分。任务划分的目的是使得各个处理器都能分配到平衡的工作负载,从而提高运算的并行性。数据划分是将数据对象划分成多个并行处理的数据子集。数据流划分是根据数据的处理过程进行划分,在不同的处理阶段进行不同的数据划分。
以下用两个例子分别介绍在共享存储器和分布存储器多处理器系统进行上节中对64000个数据累加的方法。在共享存储器系统中,假定有8个处理器以单总线方式连接。在求和运算时,数据A存储在集中共享的存储器中,每个处理器对共享数据中的划分成不同子集进行访问和累加。设Pn为处理器数,所有处理器通过分别运行以下程序对子集中的数据进行部分和计算:
sum[Pn]=0;
for(i=8000*Pn;i<8000*(Pn+1);i=i+1)
sum[Pn]=sum[Pn]+A[i]; /* sum the assigned areas */
这个循环将子集的数据从共享存储器中取出。然后将数据与部分和相加,形成部分和之后再求得总和。每个处理器的部分和也存放在共享的存储器中,用一个数组sum[]表示这些部分和。
求总和的程序段必须在各个处理器的部分和都计算完成时才开始进行,因此需要一种同步机制来协调程序的执行时间。在并行程序中,必须明确规定关键点的同步。对于本例,求总和的程序可以采用synch()函数进行同步操作。synch()函数是一个屏障同步函数,它使得所有处理器中的有关线程都执行到这一点时才继续执行以后的指令,先到达同步点的线程必须等待。即当一个或部分线程调用这个函数时,函数不返回,只有当所有的线程都调用了这个函数时,这个函数才返回,使得所有的线程都可以进行下一步的操作。
在分布消息传递型多处理器系统中控制工程网版权所有,假设有64个处理器,通过某种互连网络相互连接。进行上述求和运算的第一步是进行数据划分,将数据子集分发到各局部存储器中,数据子集存储在各局部存储器中后成为数组A1。计算步骤是先计算部分和www.cechina.cn,然后对部分和计算总和,程序为:
sum=0;
for(i=0;i<1000;i=i+1) /* loop over each array */
sum=sum+A1[i]; /* sum the local arrays */
limit=64;
half