一种多核环境下基于数组结构的无等待栈操作方法技术

技术编号:15638744 阅读:86 留言:0更新日期:2017-06-15 19:10
本发明专利技术公开了一种多核环境下基于数组结构的无等待栈操作方法。本方法为:1)主程序初始化代表栈的全局数组,即分配一个包含N个数组元素的段;2)启动m个线程,每个线程维护一存储自己运行状态的变量h

【技术实现步骤摘要】
一种多核环境下基于数组结构的无等待栈操作方法
本专利技术属于并行算法
,具体涉及到一种多核环境下基于数组结构的无等待栈操作方法。
技术介绍
随着多核处理器的迅猛普及,计算机编程模式由传统串行编程模式向线程级并行编程模式转变,以发挥出与核数量的增长相一致的实际效果。共享数据结构(例如:栈和队列)作为线程间通信的常用手段,是多线程应用的重要组成结构。为了确保多线程应用高效运行于多核平台,需要设计高性能的并发数据结构。此外,进度保障是并发数据结构需要提供的另一大特性。并发数据结构通常可分为阻塞和非阻塞这两大类。如果线程对阻塞数据结构进行操作,它可能首先需要等待另一个线程操作的完成。因此,阻塞数据结构会引发诸如死锁和优先级反转等问题。非阻塞数据结构可以确保被暂停的操作不会阻塞其它操作,从而避免上述阻塞数据结构所带来的问题。非阻塞数据结构提供以下三个层次的进度保障:无阻碍:保障系统中一个孤立运行的线程能够在有限步骤内完成任意操作;无锁:保障系统中若干线程能够在有限步骤内完成任意操作;无等待:保障系统中每个线程都能够在有限步骤内完成任意操作。无等待是并发数据结构可以提供的最强进度保障,该特性对于多线程应用和操作系统来说弥足珍贵,尤其是当它们运行于高争用环境下的时候(例如:云计算环境)。但是,无等待数据结构的设计往往比较复杂,且性能较低下。例如,当前表现最好的无等待栈算法的执行速度,甚至低于一种基于结合技术的阻塞栈算法。
技术实现思路
本专利技术公开了一种多核环境下基于数组结构的无等待栈操作方法,其目的在于保持高效执行的前提下,为线程的操作提供无等待的进度保障。栈的基本操作包括入栈、出栈、取栈顶元素、判断空等;其中,仅入栈和出栈操作会对栈进行修改;因此,与现有并行栈算法类似,本专利技术仅关注入栈和出栈操作;本领域的技术人员容易理解,本专利技术经过简单修改就能支持栈的其它操作。本专利技术公开的多核环境下基于数组结构的无等待栈操作方法总体流程如下:(1)主程序初始化代表栈的全局数组,即分配一个包含N个数组元素的段,用于后续存放入栈数据;其中,每个数组元素包含用于存储入栈数据的变量val,指向入栈请求的指针push,以及指向出栈请求的指针pop,push和pop的初始值均为0;(2)设置初始值为0的全局共享变量T和pc;其中,T为栈顶索引,pc用于指示后续出栈请求的标识符;(3)启动m个线程,每个线程thi(i=0,1,2,…,m-1)维护一个handle结构类型的变量hi来存储自己的运行状态,该结构还包含指针next、入栈伙伴指针和出栈伙伴指针;其中,每个线程的入栈伙伴指针和出栈伙伴指针均初始指向本线程;(4)利用线程handle结构类型变量中的指针next,将所有线程的运行状态链接为环状,即hi(i=0,1,2,…,m-2)的next指针指向hi+1,hm-1的next指针指向h0,使任意线程可以访问到其它线程的运行状态;(5)主程序等待接收线程对栈进行操作的请求;(6)当任意线程thi(i=0,1,2,…,m-1)要对栈进行操作时,如果thi的操作请求为入栈请求,thi执行无等待入栈操作;如果thi的操作请求为出栈请求,thi执行无等待出栈操作;如果thi的操作请求为栈的销毁请求,主程序会首先销毁栈,然后包括主程序在内的所有线程结束执行;对于栈的销毁请求之外的情况,主程序立刻继续步骤(5)。本专利技术提供的无等待入栈操作会首先利用比较并交换(CompareandSwap,CAS)原子操作,尝试将入栈数据直接存入栈顶元素的val变量,当存入失败的次数超过给定阈值P后,会在本线程的运行状态中公布本次入栈请求;其它线程会在执行无等待出栈操作时的必要情况下,尝试为该入栈请求指定合适的入栈位置,以协助该入栈请求的完成;任意线程thi执行无等待入栈操作的具体步骤如下:(2-1)利用获取并自加(Fetchandadd,FAA)原子操作,对栈顶索引T进行原子加一,获取入栈位置索引i,即执行i=FAA(&T,1);设置初始值为0的变量push_failures,用于指示将v存入全局数组失败的次数;(2-2)如果全局数组的当前长度小于i+1,首先通过分配更多包含N个数组元素的段,将数组长度扩展为不小于i+1;在全局数组中查找索引为i的元素,并将变量c设置为该元素,并利用CAS操作,尝试将入栈数据v存入c的val变量;当且仅当c的val变量尚未被其它入栈或出栈操作存入数据时,v才能被成功存入c的val变量;其中,索引为i的元素指全局数组中第i+1个元素;(2-3)判断数据v是否被成功存入c的val变量,如果是,结束本次入栈操作;否则,执行push_failures=push_failures+1,进入步骤(2-4);(2-4)判断push_failures是否大于阈值P,如果是,在本线程thi的运行状态中公布本次入栈请求r,并将r的标识符设置为入栈位置索引i的当前值,用于确保v不会被存入索引小于当前i值的元素,从而满足栈的后进先出语义,进入步骤(2-5);否则,转步骤(2-1);(2-5)执行i=FAA(&T,1),即获取入栈位置索引i;(2-6)如果全局数组的当前长度小于i+1,首先通过分配更多包含N个数组元素的段,将数组长度扩展为不小于i+1;在全局数组中查找索引为i的元素,并将变量c设置为该元素,并利用CAS操作,尝试将c的push指针从0改为指向r;当且仅当c的push指针值为0时,才会成功指向r;(2-7)判断c的push指针是否指向r,如果是,尝试将c指定为r的入栈位置;否则,转步骤(2-9);(2-8)判断c是否指定为r的入栈位置,如果是,转步骤(2-10);(2-9)判断r是否已有指定元素进行入栈,如果是,进入步骤(2-10);否则,转步骤(2-5);(2-10)将v存入r被指定的入栈元素的val变量中,结束本次入栈操作。本专利技术提供的无等待出栈操作会首先读取栈顶索引,然后从该索引所指的位置开始,朝索引值递减的方向依次尝试从相应元素出栈,当出栈失败的次数超过给定阈值P后,会在本线程的运行状态中公布本次出栈请求;其它线程会在执行无等待出栈操作时的必要情况下,尝试为该出栈请求指定合适的出栈位置,以协助该出栈请求的完成;任意线程thi执行无等待出栈操作的具体步骤如下:(3-1)读取栈顶索引的值,并将该值存入一变量t;如果全局数组的当前长度小于t+1,首先通过分配更多包含N个数组元素的段,将数组长度扩展为不小于t+1;在全局数组中查找索引为t的元素,并将变量c设置为该元素;(3-2)设置初始值为0的变量pop_failures,用于记录出栈失败的次数;(3-3)判断c是否为栈底,如果是,返回空,结束本次出栈操作;否则,首先执行t=t-1,然后在全局数组中查找索引为t的元素,并将c设置为该元素;(3-4)将c作为快速出栈函数的输入参数,调用快速出栈函数;当且仅当快速出栈函数的返回值为1时,本次出栈操作才能从c中出栈;(3-5)判断快速出栈函数的返回值是否为1,如果是,转步骤(3-11);否则,执行pop_failures=pop_failures+1;(3-6)判断pop_failures是否大于P,如果是,在本线程thi的本文档来自技高网...
一种多核环境下基于数组结构的无等待栈操作方法

【技术保护点】
一种多核环境下基于数组结构的无等待栈操作方法,其步骤为:1)主程序初始化代表栈的全局数组,即分配一个包含N个数组元素的段;其中,每个数组元素包含用于存储入栈数据的变量val,指向入栈请求的指针push,以及指向出栈请求的指针pop;初始化两全局共享变量T、pc;其中,T为栈顶索引,pc为指示出栈请求的标识符;2)启动m个线程,每个线程th

【技术特征摘要】
1.一种多核环境下基于数组结构的无等待栈操作方法,其步骤为:1)主程序初始化代表栈的全局数组,即分配一个包含N个数组元素的段;其中,每个数组元素包含用于存储入栈数据的变量val,指向入栈请求的指针push,以及指向出栈请求的指针pop;初始化两全局共享变量T、pc;其中,T为栈顶索引,pc为指示出栈请求的标识符;2)启动m个线程,每个线程thi维护一存储自己运行状态的变量hi;该变量hi包含指针next、入栈伙伴指针和出栈伙伴指针;其中,线程thi的入栈伙伴指针和出栈伙伴指针均初始指向线程thi;3)利用变量hi中的next指针,将该m个线程的运行状态链接为环状;4)该主程序等待接收线程对栈进行操作的请求;当线程thi对栈进行操作时,如果该线程thi的操作请求为入栈请求,则该线程thi执行无等待入栈操作;如果该线程thi的操作请求为出栈请求,则该线程thi执行无等待出栈操作;如果该线程thi的操作请求为栈的销毁请求,则该主程序首先销毁栈,然后包括主程序在内的所有线程结束执行。2.如权利要求1所述的方法,其特征在于,该线程thi执行无等待入栈操作的方法为:a)对栈顶索引T进行原子加一,获取入栈位置索引i;设置变量push_failures,用于记录将入栈数据v存入全局数组失败的次数;b)如果全局数组的当前长度小于i+1,则通过分配多个包含N个数组元素的段,将全局数组的长度扩展为不小于i+1;在全局数组中查找索引为i的元素,并将变量c设置为该元素,然后尝试将入栈数据v存入元素c的变量val;其中,索引为i的元素指全局数组中第i+1个元素;c)判断入栈数据v是否被成功存入元素c的变量val,如果是,则结束本次入栈操作;否则,执行push_failures=push_failures+1;判断当前push_failures值是否大于阈值P,如果是,则该线程thi的运行状态中公布本次入栈请求r,并将入栈请求r的标识符设置为入栈位置索引i的当前值,执行步骤d);否则,执行步骤a);d)对栈顶索引T进行原子加一,获取入栈位置索引i;如果全局数组的当前长度小于i+1,则通过分配多个包含N个数组元素的段,将全局数组的长度扩展为不小于i+1;在全局数组中查找索引为i的元素,并将变量c设置为该元素,如果能够将元素c的指向入栈请求的指针push改为指向该入栈请求r,则将元素c指定为该入栈请求r的入栈位置,否则判断该入栈请求r是否已有指定元素进行入栈,如果是,则将入栈数据v存入该入栈请求r被指定的入栈元素的val变量中,结束本次入栈操作;如果该入栈请求r没有指定元素进行入栈,则重复步骤d)。3.如权利要求1所述的方法,其特征在于,该线程thi执行无等待出栈操作的方法为:a)读取栈顶索引的值,并将该值存入一变量t;如果全局数组的当前长度小于t+1,则通过分配多个包含N个数组元素的段,将全局数组长度扩展为不小于t+1;在全局数组中查找索引为t的元素,并将变量c设置为该元素;设置一变量pop_failures,用于记录出栈失败的次数;b)判断元素c是否为栈底,如果是,则返回空,并结束本次出栈操作;否则,首先执行t=t-1,然后在全局数组中查找索引为t的元素,并将变量c设置为该元素;c)将当前元素c作为快速出栈函数的输入参数,调用快速出栈函数,如果快速出栈函数的出栈操作能从c中出栈,则将线程thi的出栈伙伴指针所指向的线程th维护的变量h作为帮助出栈函数的输入参数,调用帮助出栈函数,其中,变量h的next指针指向线程th’的变量h’,然后将线程thi的出栈伙伴指针指向变量h’对应的线程th’;然后返回元素c的val变量存放的值,即完成出栈操作;d)如果快速出栈函数的的出栈操作不能从c中出栈,则执行pop_failures=pop_failures+1;然后判断pop_failures是否大于设定阈值P,如果是,则该线程thi的运行状态中公布本次出栈请求q,并在该出栈请求q中记录元素c及其索引值,以及通过对共享变量pc进行原子加一操作获取该出栈请...

【专利技术属性】
技术研发人员:彭亚琼郝志宇刘永继李大辉崔磊
申请(专利权)人:中国科学院信息工程研究所
类型:发明
国别省市:北京,11

网友询问留言 已有0条评论
  • 还没有人留言评论。发表了对其他浏览者有用的留言会获得科技券。

1