CN106843806A - 一种多核环境下基于数组结构的无等待栈操作方法 - Google Patents
一种多核环境下基于数组结构的无等待栈操作方法 Download PDFInfo
- Publication number
- CN106843806A CN106843806A CN201611186222.2A CN201611186222A CN106843806A CN 106843806 A CN106843806 A CN 106843806A CN 201611186222 A CN201611186222 A CN 201611186222A CN 106843806 A CN106843806 A CN 106843806A
- Authority
- CN
- China
- Prior art keywords
- stack
- thread
- variable
- stacking
- request
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Granted
Links
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F9/00—Arrangements for program control, e.g. control units
- G06F9/06—Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
- G06F9/30—Arrangements for executing machine instructions, e.g. instruction decode
- G06F9/30003—Arrangements for executing specific machine instructions
- G06F9/3004—Arrangements for executing specific machine instructions to perform operations on memory
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F9/00—Arrangements for program control, e.g. control units
- G06F9/06—Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
- G06F9/46—Multiprogramming arrangements
- G06F9/52—Program synchronisation; Mutual exclusion, e.g. by means of semaphores
- G06F9/526—Mutual exclusion algorithms
Landscapes
- Engineering & Computer Science (AREA)
- Software Systems (AREA)
- Theoretical Computer Science (AREA)
- Physics & Mathematics (AREA)
- General Engineering & Computer Science (AREA)
- General Physics & Mathematics (AREA)
- Executing Machine-Instructions (AREA)
Abstract
本发明公开了一种多核环境下基于数组结构的无等待栈操作方法。本方法为:1)主程序初始化代表栈的全局数组,即分配一个包含N个数组元素的段;2)启动m个线程,每个线程维护一存储自己运行状态的变量hi;该变量hi包含指针next、入栈伙伴指针和出栈伙伴指针;3)利用变量hi中的next指针,将该m个线程的运行状态链接为环状;4)该主程序等待接收线程对栈进行操作的请求;如果线程的操作请求为入栈请求,则执行无等待入栈操作;如果为出栈请求,则执行无等待出栈操作;如果销毁请求,则该主程序首先销毁栈,然后包括主程序在内的所有线程结束执行。本发明具有高并行度、低复杂度,为线程的操作提供无等待的进度保障。
Description
技术领域
本发明属于并行算法技术领域,具体涉及到一种多核环境下基于数组结构的无等待栈操作方法。
背景技术
随着多核处理器的迅猛普及,计算机编程模式由传统串行编程模式向线程级并行编程模式转变,以发挥出与核数量的增长相一致的实际效果。共享数据结构(例如:栈和队列)作为线程间通信的常用手段,是多线程应用的重要组成结构。为了确保多线程应用高效运行于多核平台,需要设计高性能的并发数据结构。此外,进度保障是并发数据结构需要提供的另一大特性。并发数据结构通常可分为阻塞和非阻塞这两大类。如果线程对阻塞数据结构进行操作,它可能首先需要等待另一个线程操作的完成。因此,阻塞数据结构会引发诸如死锁和优先级反转等问题。
非阻塞数据结构可以确保被暂停的操作不会阻塞其它操作,从而避免上述阻塞数据结构所带来的问题。非阻塞数据结构提供以下三个层次的进度保障:
无阻碍:保障系统中一个孤立运行的线程能够在有限步骤内完成任意操作;
无锁:保障系统中若干线程能够在有限步骤内完成任意操作;
无等待:保障系统中每个线程都能够在有限步骤内完成任意操作。
无等待是并发数据结构可以提供的最强进度保障,该特性对于多线程应用和操作系统来说弥足珍贵,尤其是当它们运行于高争用环境下的时候(例如:云计算环境)。但是,无等待数据结构的设计往往比较复杂,且性能较低下。例如,当前表现最好的无等待栈算法的执行速度,甚至低于一种基于结合技术的阻塞栈算法。
发明内容
本发明公开了一种多核环境下基于数组结构的无等待栈操作方法,其目的在于保持高效执行的前提下,为线程的操作提供无等待的进度保障。栈的基本操作包括入栈、出栈、取栈顶元素、判断空等;其中,仅入栈和出栈操作会对栈进行修改;因此,与现有并行栈算法类似,本发明仅关注入栈和出栈操作;本领域的技术人员容易理解,本发明经过简单修改就能支持栈的其它操作。
本发明公开的多核环境下基于数组结构的无等待栈操作方法总体流程如下:
(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)。
本发明提供的无等待入栈操作会首先利用比较并交换(Compare and Swap,CAS)原子操作,尝试将入栈数据直接存入栈顶元素的val变量,当存入失败的次数超过给定阈值P后,会在本线程的运行状态中公布本次入栈请求;其它线程会在执行无等待出栈操作时的必要情况下,尝试为该入栈请求指定合适的入栈位置,以协助该入栈请求的完成;任意线程thi执行无等待入栈操作的具体步骤如下:
(2-1)利用获取并自加(Fetch and add,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的运行状态中公布本次出栈请求q,并在q中记录c及其索引值,q的标识符通过对共享变量pc进行原子加一操作来获取,即q的标识符=FAA(&pc,1);否则,转步骤(3-3);
(3-7)将本线程thi的handle结构类型的变量h作为帮助出栈函数的输入参数,调用帮助出栈函数;当帮助出栈函数返回时,当前线程thi可以从q中获取最终出栈结果;
(3-8)判断出栈结果是否为空,如果是,返回空,结束本次出栈操作;否则,从q中读取指定出栈元素,并将c设置为该元素;当前线程thi可以从q中获取最终出栈结果,分为两种情况:(1)返回空;(2)有指定出栈元素。
(3-9)统计c所在段s中已出栈元素和无用元素的总数n;
(3-10)判断n是否等于N,如果是,删除s然后进行步骤(3-11),否则直接进行步骤(3-11);其中,N为s所包含的数组元素的总数;
(3-11)假定当前出栈伙伴指针所指向的线程为th,将th维护的handle结构类型的变量h作为帮助出栈函数的输入参数,调用帮助出栈函数;
(3-12)假定h的next指针指向h’,将线程thi的出栈伙伴指针指向h’对应的线程;
(3-13)返回c的val变量存放的值,即完成出栈,结束本次出栈操作。
进一步,无等待出栈操作的特征在于,步骤(3-4)需要调用快速出栈函数,该函数包括如下步骤:
(4-1)读取本函数的输入元素c,将c作为帮助入栈函数的输入参数,调用帮助入栈函数;
(4-2)竞争c的出栈权,即利用CAS操作,尝试将c的pop指针从0改为-1;如果CAS操作的返回值非0,说明竞争成功;
(4-3)判断竞争是否成功,如果是,统计c所在段s中已出栈元素和无用元素的总数n,执行步骤(4-4);否则,从c中出栈失败,返回0,结束快速出栈函数的执行;
(4-4)判断n是否等于N,如果是,删除s;其中,N为s所包含的数组元素的总数;
(4-5)判断c的val变量是否存放有效值,如果是,则从c中出栈成功,返回1;否则,从c中出栈失败,返回0。
进一步,无等待出栈操作的特征在于,步骤(3-7)和步骤(3-11)需要调用帮助出栈函数,该函数包括如下步骤:
(5-1)读取本函数的输入参数h;
(5-2)通过读取h中存储的运行状态,判断与h对应的线程是否存在需要帮助的出栈请求q,如果是,进入步骤(5-3);否则,结束帮助出栈函数的执行;
(5-3)读取q中记录的元素c和c的索引,并将c的索引赋值给变量i;
(5-4)判断c是否为栈底,如果是,尝试指定q的出栈结果为返回空,结束帮助出栈函数的执行;否则,执行i=i-1,在全局数组中查找索引为i的元素,并将变量c设置为该元素;
(5-5)将c作为帮助入栈函数的输入参数,调用帮助入栈函数;
(5-6)竞争c的出栈权,即利用CAS操作,尝试将c的pop指针从0改为指向q,并使用变量ret保存CAS操作的返回值;
(5-7)判断c的pop指针是否指向q,如果是,进入步骤(5-8);否则,转步骤(5-11);
(5-8)判断c的val变量是否存放有效值,如果是,尝试指定q从c中出栈,结束帮助出栈函数的执行;
(5-9)判断ret是否为0,如果是,转步骤(5-11);否则,统计c所在段s中已出栈元素和无用元素的总数n;
(5-10)判断n是否等于N,如果是,删除s,然后执行步骤(5-11);如果n不等于N,则执行(5-11);
(5-11)判断q是否已被指定出栈结果,如果是,结束帮助出栈函数的执行;否则,转步骤(5-4)。
进一步,快速出栈函数和帮助出栈函数的特征在于,步骤(4-1)和步骤(5-5)需要调用帮助入栈函数,该函数包括如下步骤:
(6-1)读取本函数的输入元素c,如果c的val变量中尚未存放有效值,则利用CAS操作,尝试将无效值存入c的val变量中,使c成为无用元素;
(6-2)判断c的val变量是否存放有效值,如果是,结束帮助入栈函数的执行;
(6-3)判断c的push指针是否已指向某入栈请求,如果是,转步骤(6-11);否则,读取本线程thi的入栈伙伴指针所指向的线程,并将变量th设置为该线程;
(6-4)判断本线程thi是否在本周期内尝试帮助过th入栈,并且相应入栈请求已完成,如果否,则直接进行步骤(6-5);如果是,则假定th维护的handle结构类型的变量为h,h的next指针指向h’,将th设置为h’对应的线程,并使本线程thi的入栈伙伴指针指向th;
(6-5)判断th是否有需要帮助的入栈请求r’,如果是,进入步骤(6-6);否则,转步骤(6-8);
(6-6)判断r’的标识符是否小于或等于c的索引,如果是,尝试将c预留给r’,即利用CAS操作,尝试将c的push指针从0改为指向r’,若成功,CAS操作的返回值为非0;否则,转步骤(6-8);
(6-7)判断是否成功将c预留给r’,如果是,进入步骤(6-8);否则,转步骤(6-9);
(6-8)假定th维护的handle结构类型的变量为h,h的next指针指向h’,将本线程thi的入栈伙伴指针指向h’对应的线程;
(6-9)如果c的push指针当前值为0,则利用CAS操作,尝试将c的push指针从0更改为-1;经过该步骤的处理,c的push指针要么被其它线程设置为指向某入栈请求,要么被设置为-1;
(6-10)判断c的push指针是否为-1,如果是,结束帮助入栈函数的执行;否则,进入步骤(6-11);
(6-11)读取c的push指针指向的入栈请求r;
(6-12)判断r的标识符是否小于或等于c的索引,如果是,尝试将c指定为r的入栈位置;否则,结束帮助入栈函数的执行;
(6-13)判断c是否指定为r的入栈位置,如果是,将r的数据v存入c的val变量;结束帮助入栈函数的执行。
与已公开的方法相比,本发明具有如下优点:
1)高并行度:现有并行栈算法主要利用带有栈顶指针的单向链表来建立栈结构;当线程需要执行入栈或出栈操作时,需要反复执行CAS操作,尝试修改栈顶指针,直到CAS操作成功为止;在这类栈算法中,栈顶指针是线程的唯一竞争点,使多个线程只能顺序执行入栈和出栈操作,极大限制了栈算法的并行度,从而无法充分利用多核平台强大的计算资源;为了提高栈算法的并行度,本发明利用数组来建立栈结构,分散线程的竞争点,从而提高入栈和出栈操作并行执行的可能性;此外,由于一个数组元素可能存放的是无效值或已出栈,为了方便清理这些元素占据的内存空间,本发明将全局数组划分为多个段,当一个段中的所有元素都存放的是无效值或已出栈时,会删除该段并释放它的内存空间。
2)低复杂度:在基于链表的栈算法中,由于栈顶指针在同一时刻仅能被一个线程成功修改,某线程会因为其它线程的阻碍而无法完成入栈或出栈操作;为了提供无等待的进度保障,现有方法往往需要在所有操作中添加复杂的控制流程,从而牺牲了算法的性能;本发明提供的无等待栈算法将入栈操作分散到不同数组元素,使入栈操作仅会因为出栈操作的阻碍而失败,并且入栈操作不会阻碍出栈操作的执行,因此仅需在出栈操作中添加控制流程,保障其它线程能在有限步骤内完成相应操作,该算法设计简洁,方便应用到实际系统中;
附图说明
图1是本发明所基于的数据结构;
图2是本发明的总体流程;
图3是无等待入栈操作的执行流程;
图4是无等待出栈操作的执行流程;
图5是快速出栈函数的执行流程;
图6是帮助出栈函数的执行流程;
图7是帮助入栈函数的执行流程。
具体实施方式
为了使本发明的目的、技术方案及优点更加清楚明白,以下结合附图和实施例,对本发明进行进一步详细说明。应当理解,此处所描述的具体实施例仅仅用以解释本发明,并不用于限定本发明。凡在本发明的精神和原则之内所作的任何修改、等同替换和改进等,均应包含在本发明的保护范围之内。
本发明利用如图1所示数据结构来构建栈,将全局数组划分为多个包含N个数组元素的段,并且段与段之间构成双向链表结构。其中,每个段都有唯一标识符id,指向下一个段的next指针,指向前一个段的prev指针,以及用于统计已出栈元素和无用元素数量的变量counter。例如,标识符为1的段的prev和next指针,分别指向标识符为0和2的段。全局数组中的第一个段的prev指针和最后一个段的next指针则为空。此外,假定某数组元素的全局索引为i,那么它对应于标识符为i/N的段中第i%N+1个数组元素。本发明在栈的初始化阶段仅分配一个段,在程序执行期间再按需分配更多段。
本发明公开的多核环境下基于数组结构的无等待栈操作方法总体流程如图2所示,其步骤为:
(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)。
本发明提供的无等待入栈操作流程如图3所示,具体步骤如下:
(2-1)对栈顶索引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);
(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变量中,结束本次入栈操作。
本发明提供的无等待出栈操作流程如图4所示,具体步骤如下:
(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的运行状态中公布本次出栈请求q,并在q中记录c及其索引值,q的标识符通过对共享变量pc进行原子加一操作来获取,即q的标识符=FAA(&pc,1);否则,转步骤(3-3);
(3-7)将本线程thi的handle结构类型的变量h作为帮助出栈函数的输入参数,调用帮助出栈函数;当帮助出栈函数返回时,当前线程thi可以从q中获取最终出栈结果;
(3-8)判断出栈结果是否为空,如果是,返回空,结束本次出栈操作;否则,从q中读取指定出栈元素,并将c设置为该元素;当前线程thi可以从q中获取最终出栈结果,分为两种情况:(1)返回空;(2)有指定出栈元素。
(3-9)统计c所在段s中已出栈元素和无用元素的总数n;
(3-10)判断n是否等于N,如果是,删除s然后进行步骤(3-11),否则直接进行步骤(3-11);其中,N为s所包含的数组元素的总数;
(3-11)假定当前出栈伙伴指针所指向的线程为th,将th维护的handle结构类型的变量h作为帮助出栈函数的输入参数,调用帮助出栈函数;
(3-12)假定h的next指针指向h’,将线程thi的出栈伙伴指针指向h’对应的线程;
(3-13)返回c的val变量存放的值,即完成出栈,结束本次出栈操作。
进一步,无等待出栈操作的特征在于,步骤(3-4)需要调用快速出栈函数,该函数的执行流程如图5所示,具体步骤如下:
(4-1)读取本函数的输入元素c,将c作为帮助入栈函数的输入参数,调用帮助入栈函数;
(4-2)竞争c的出栈权,即利用CAS操作,尝试将c的pop指针从0改为-1;如果CAS操作的返回值非0,说明竞争成功;
(4-3)判断竞争是否成功,如果是,统计c所在段s中已出栈元素和无用元素的总数n,执行步骤(4-4);否则,从c中出栈失败,返回0,结束快速出栈函数的执行;
(4-4)判断n是否等于N,如果是,删除s;其中,N为s所包含的数组元素的总数;
(4-5)判断c的val变量是否存放有效值,如果是,则从c中出栈成功,返回1;否则,从c中出栈失败,返回0。
进一步,无等待出栈操作的特征在于,步骤(3-7)和步骤(3-11)需要调用帮助出栈函数,该函数的执行流程如图6所示,具体步骤如下:
(5-1)读取本函数的输入参数h;
(5-2)通过读取h中存储的运行状态,判断与h对应的线程是否存在需要帮助的出栈请求q,如果是,进入步骤(5-3);否则,结束帮助出栈函数的执行;
(5-3)读取q中记录的元素c和c的索引,并将c的索引赋值给变量i;
(5-4)判断c是否为栈底,如果是,尝试指定q的出栈结果为返回空,结束帮助出栈函数的执行;否则,执行i=i-1,在全局数组中查找索引为i的元素,并将变量c设置为该元素;
(5-5)将c作为帮助入栈函数的输入参数,调用帮助入栈函数;
(5-6)竞争c的出栈权,即利用CAS操作,尝试将c的pop指针从0改为指向q,并使用变量ret保存CAS操作的返回值;
(5-7)判断c的pop指针是否指向q,如果是,进入步骤(5-8);否则,转步骤(5-11);
(5-8)判断c的val变量是否存放有效值,如果是,尝试指定q从c中出栈,结束帮助出栈函数的执行;
(5-9)判断ret是否为0,如果是,转步骤(5-11);否则,统计c所在段s中已出栈元素和无用元素的总数n;
(5-10)判断n是否等于N,如果是,删除s,然后执行步骤(5-11);如果n不等于N,则执行(5-11);
(5-11)判断q是否已被指定出栈结果,如果是,结束帮助出栈函数的执行;否则,转步骤(5-4)。
进一步,快速出栈函数和帮助出栈函数的特征在于,步骤(4-1)和步骤(5-5)需要调用帮助入栈函数,该函数的执行流程如图7所示,具体步骤如下:
(6-1)读取本函数的输入元素c,如果c的val变量中尚未存放有效值,则利用CAS操作,尝试将无效值存入c的val变量中,使c成为无用元素;
(6-2)判断c的val变量是否存放有效值,如果是,结束帮助入栈函数的执行;
(6-3)判断c的push指针是否已指向某入栈请求,如果是,转步骤(6-11);否则,读取本线程thi的入栈伙伴指针所指向的线程,并将变量th设置为该线程;
(6-4)判断本线程thi是否在本周期内尝试帮助过th入栈,并且相应入栈请求已完成,如果否,则直接进行步骤(6-5);如果是,假定th维护的handle结构类型的变量为h,h的next指针指向h’,将th设置为h’对应的线程,并使本线程thi的入栈伙伴指针指向th;
(6-5)判断th是否有需要帮助的入栈请求r’,如果是,进入步骤(6-6);否则,转步骤(6-8);
(6-6)判断r’的标识符是否小于或等于c的索引,如果是,尝试将c预留给r’,即利用CAS操作,尝试将c的push指针从0改为指向r’,若成功,CAS操作的返回值为非0;否则,转步骤(6-8);
(6-7)判断是否成功将c预留给r’,如果是,进入步骤(6-8);否则,转步骤(6-9);
(6-8)假定th维护的handle结构类型的变量为h,h的next指针指向h’,将本线程thi的入栈伙伴指针指向h’对应的线程;
(6-9)如果c的push指针当前值为0,则利用CAS操作,尝试将c的push指针从0更改为-1;经过该步骤的处理,c的push指针要么被其它线程设置为指向某入栈请求,要么被设置为-1;
(6-10)判断c的push指针是否为-1,如果是,结束帮助入栈函数的执行;否则,进入步骤(6-11);
(6-11)读取c的push指针指向的入栈请求r;
(6-12)判断r的标识符是否小于或等于c的索引,如果是,尝试将c指定为r的入栈位置;否则,结束帮助入栈函数的执行;
(6-13)判断c是否指定为r的入栈位置,如果是,将r的数据v存入c的val变量;结束帮助入栈函数的执行。
Claims (7)
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进行原子加一操作获取该出栈请求q的标识符,然后执行步骤e);否则,执行步骤b);
e)将该线程thi的变量h作为帮助出栈函数的输入参数,调用帮助出栈函数;如果帮助出栈函数返回为空,并结束本次出栈操作;如果返回该出栈请求q中的指定出栈元素c,则统计元素c所在段s中已出栈元素和无用元素的总数n;如果n等于N,则删除段s;其中,N为s所包含的数组元素的总数;将线程thi的出栈伙伴指针所指向的线程th维护的变量h作为帮助出栈函数的输入参数,调用帮助出栈函数,其中,变量h的next指针指向线程th’的变量h’,然后将线程thi的出栈伙伴指针指向变量h’对应的线程th’;然后返回元素c的val变量存放的值,即完成出栈操作。
4.如权利要求3所述的方法,其特征在于,所述快速出栈函数的处理流程为:
a1)该线程thi将输入元素c作为帮助入栈函数的输入参数,调用帮助入栈函数;
a2)该线程thi竞争该元素c的出栈权,如果竞争成功,则统计元素c所在段s中已出栈元素和无用元素的总数n,执行步骤a3);否则,结束快速出栈函数的执行;
a3)判断n是否等于N,如果是,则删除段s;然后判断元素c的val变量是否存放有效值,如果是,则从元素c中出栈成功;如果未存放有效值,则从元素c中出栈失败。
5.如权利要求3所述的方法,其特征在于,所述帮助出栈函数的处理流程为:
b1)根据输入变量h中存储的运行状态,判断变量h对应的线程是否存在需要帮助的出栈请求q,如果是,则读取出栈请求q中记录的元素c及其索引,并将元素c的索引赋值给变量i;否则,结束帮助出栈函数的执行;
b2)判断元素c是否为栈底,如果是,则出栈请求q返回空,结束帮助出栈函数的执行;否则,执行i=i-1,在全局数组中查找索引为i的元素,并将变量c设置为该元素;
b3)将元素c作为帮助入栈函数的输入参数,调用帮助入栈函数;
b4)该线程thi为出栈请求q竞争该元素c的出栈权,如果竞争成功,则判断元素c的val变量是否存放有效值,如果是,则出栈请求q从元素c中出栈,结束帮助出栈函数的执行;然后统计元素c所在段s中已出栈元素和无用元素的总数n;如果竞争失败,则进行步骤b6);
b5)判断n是否等于N,如果是,则删除段s;如果否,则进行步骤b6);
b6)判断出栈请求q是否已被指定出栈结果,如果是,则结束帮助出栈函数的执行;否则执行步骤b2)。
6.如权利要求4或5所述的方法,其特征在于,所述帮助入栈函数的处理流程为:
c1)判断输入元素c的val变量中是否存放有效值,如果未存放,则尝试将无效值存入c的val变量中,使c成为无用元素;然后再次判断c的val变量是否存放有效值,如果是,结束帮助入栈函数的执行;
c2)判断c的push指针是否已指向某入栈请求,如果是,转步骤c6);否则,读取本线程thi的入栈伙伴指针所指向的线程,并将变量th设置为该线程;判断本线程thi是否在本周期内尝试帮助过th入栈,并且相应入栈请求已完成,如果是,则将th设置为h’对应的线程,并使本线程thi的入栈伙伴指针指向th;判断线程th是否有需要帮助的入栈请求r’,如果是,进入步骤c3);否则,转步骤c4);其中,th维护的变量为h,h的next指针指向h’;
c3)判断r’的标识符是否小于或等于c的索引,如果是,则尝试将c预留给r’,即尝试将c的push指针从0改为指向r’,然后判断是否成功将c预留给r’,如果是,则进入步骤c4);否则,转步骤c5);
c4)假定线程th维护的变量为h,h的next指针指向h’,将本线程thi的入栈伙伴指针指向h’对应的线程;
c5)如果c的push指针当前值为0,则尝试将c的push指针从0更改为-1;判断c的push指针是否为-1,如果是,结束帮助入栈函数的执行;否则,进入步骤c6);
c6)读取c的push指针指向的入栈请求r,并判断r的标识符是否小于或等于c的索引,如果是,并且c被成功指定为r的入栈位置,则将r的数据v存入c的val变量;结束帮助入栈函数的执行。
7.如权利要求1所述的方法,其特征在于,变量hi为handle结构类型的变量。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN201611186222.2A CN106843806B (zh) | 2016-12-20 | 2016-12-20 | 一种多核环境下基于数组结构的无等待栈操作方法 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN201611186222.2A CN106843806B (zh) | 2016-12-20 | 2016-12-20 | 一种多核环境下基于数组结构的无等待栈操作方法 |
Publications (2)
Publication Number | Publication Date |
---|---|
CN106843806A true CN106843806A (zh) | 2017-06-13 |
CN106843806B CN106843806B (zh) | 2019-04-26 |
Family
ID=59140033
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN201611186222.2A Active CN106843806B (zh) | 2016-12-20 | 2016-12-20 | 一种多核环境下基于数组结构的无等待栈操作方法 |
Country Status (1)
Country | Link |
---|---|
CN (1) | CN106843806B (zh) |
Cited By (2)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
WO2019071721A1 (zh) * | 2017-10-09 | 2019-04-18 | 深圳市沃特沃德股份有限公司 | 操作响应方法、装置和车载系统 |
CN113743582A (zh) * | 2021-08-06 | 2021-12-03 | 北京邮电大学 | 基于栈混洗的新型通道混洗方法和装置 |
Citations (4)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
US20080250203A1 (en) * | 2007-04-09 | 2008-10-09 | Sap Ag | Wait-free parallel data cache |
CN101763289A (zh) * | 2009-09-25 | 2010-06-30 | 中国人民解放军国防科学技术大学 | 一种基于共享内存的消息传递方法 |
CN104809027A (zh) * | 2015-04-21 | 2015-07-29 | 浙江大学 | 一种基于无锁缓冲区的数据采集方法 |
CN104951299A (zh) * | 2015-06-04 | 2015-09-30 | 长沙新弘软件有限公司 | 一种基于原子操作的信号量链表式堆栈方法 |
-
2016
- 2016-12-20 CN CN201611186222.2A patent/CN106843806B/zh active Active
Patent Citations (4)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
US20080250203A1 (en) * | 2007-04-09 | 2008-10-09 | Sap Ag | Wait-free parallel data cache |
CN101763289A (zh) * | 2009-09-25 | 2010-06-30 | 中国人民解放军国防科学技术大学 | 一种基于共享内存的消息传递方法 |
CN104809027A (zh) * | 2015-04-21 | 2015-07-29 | 浙江大学 | 一种基于无锁缓冲区的数据采集方法 |
CN104951299A (zh) * | 2015-06-04 | 2015-09-30 | 长沙新弘软件有限公司 | 一种基于原子操作的信号量链表式堆栈方法 |
Non-Patent Citations (1)
Title |
---|
CHAORAN YANG: ""A Wait-free Queue as Fast as Fetch-and-Add"", 《ACM SIGPLAN NOTICES》 * |
Cited By (3)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
WO2019071721A1 (zh) * | 2017-10-09 | 2019-04-18 | 深圳市沃特沃德股份有限公司 | 操作响应方法、装置和车载系统 |
CN113743582A (zh) * | 2021-08-06 | 2021-12-03 | 北京邮电大学 | 基于栈混洗的新型通道混洗方法和装置 |
CN113743582B (zh) * | 2021-08-06 | 2023-11-17 | 北京邮电大学 | 基于栈混洗的新型通道混洗方法和装置 |
Also Published As
Publication number | Publication date |
---|---|
CN106843806B (zh) | 2019-04-26 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
US7890722B1 (en) | Sequentially performed compound compare-and-swap | |
CN104809179B (zh) | 访问哈希表的装置和方法 | |
US5586331A (en) | Duplicated logic and interconnection system for arbitration among multiple information processors | |
US6247108B1 (en) | Memory management during processing of binary decision diagrams in a computer system | |
US20060161737A1 (en) | Concurrency technique for shared objects | |
CN105468298B (zh) | 一种基于日志结构合并树的键值存储方法 | |
CN103930883B (zh) | 用于响应于矢量访问指令的交叉数据访问的方法和装置 | |
JPH03129426A (ja) | 分類加速装置のための速度及びメモリー制御 | |
CN101432702A (zh) | 在事务处理码内对存储器分配和解除分配的系统和方法 | |
CN105608162B (zh) | 文件处理方法和装置 | |
Duri et al. | Application and experimental evaluation of state space reduction methods for deadlock analysis in Ada | |
JPH04225431A (ja) | 命令キャッシュ効率を増大するコンピュータ命令をコンパイルする方法 | |
JP6937759B2 (ja) | データベース操作方法及び装置 | |
EP0221358A2 (en) | Sort string generation in a staged storage system | |
CN104216684B (zh) | 一种多核并行系统及其数据处理方法 | |
CN106843806A (zh) | 一种多核环境下基于数组结构的无等待栈操作方法 | |
CN107992577A (zh) | 一种哈希表数据冲突处理方法及装置 | |
DE69922238T2 (de) | Mechanismus zur blockierung von ladeoperationen auf adressengeneration von speicherbefehlen und universeller abhängigkeitsvektor | |
JPH03116323A (ja) | リバウンド分類装置を併合装置として使用する分類加速装置 | |
CN110362394A (zh) | 任务处理方法及装置、存储介质、电子装置 | |
Kogge et al. | VLSI and rule-based systems | |
Carver et al. | A stateful approach to testing monitors in multithreaded programs | |
JP2003528390A (ja) | インタプリタによりコンピュータプログラムを実行する方法、コンピュータシステムならびにコンピュータプログラムプロダクト | |
Hartman et al. | Symmetry in gardens of eden | |
CN107018078A (zh) | 多分支跳转协处理方法及装置 |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
PB01 | Publication | ||
PB01 | Publication | ||
SE01 | Entry into force of request for substantive examination | ||
SE01 | Entry into force of request for substantive examination | ||
GR01 | Patent grant | ||
GR01 | Patent grant |