发明内容
目的:为了克服现有技术中存在的串行拓扑分析实时性较差的不足,本发明提供一种基于GPU加速的电网拓扑分析高性能计算方法,CPU进行拓扑数据预处理,而将大规模的拓扑搜索步骤置于GPU上完成,设计相关的并行算法,从而实现电网拓扑分析的并行计算。对实际电网进行的测试结果表明,该方法具有优异的实时性和稳定能,能够满足电网实时在线拓扑分析的需求。
技术方案:为解决上述技术问题,本发明采用的技术方案为:
一种基于GPU加速的电网拓扑分析高性能计算方法,包括如下步骤:
CPU对电网调度控制***电网模型进行图论抽象,得到CPU端的压缩邻接数组h_Adj1,h_Adj2,h_Adj1代表全网物理节点的第一压缩邻接数组,h_Adj2代表全网物理节点的第二压缩邻接数组;
GPU调用内核函数Topo_Kernel_1<BlockNum,ThreadNum>,将CPU端全网物理节点的第一压缩邻接数组h_Adj1传到GPU端全网物理节点的第一压缩邻接数组d_Adj1,根据GPU端物理节点的标志位前驱数组d_Frontier[d_Adj1[i]]=1,表示在下一次启动时,d_Adj1[i]号物理节点需要启动,GPU端物理节点的标志位结果数组d_Visited[i]=m,表示第i个物理节点属于m号计算节点,将各计算节点包含的物理节点序号,保存在CalculationNodeMap中,再根据CPU端全网物理节点的第二压缩邻接数组h_Adj2,得到CPU端计算节点的压缩邻接数组h_Adj_Island;BlockNum表示同时启动的线程块数,ThreadNum表示每一个线程块内,同时启动的线程数;
GPU调用内核函数Topo_Kernel_2<BlockNum,ThreadNum>,将CPU端计算节点的压缩邻接数组h_Adj_Island传到GPU端计算节点的压缩邻接数组d_Adj_Island,根据GPU端计算节点的标志位前驱数组d_Frontier_Island[d_Adj_Island[i]]=1,表示在下一次启动时,d_Adj_Island[i]号节点需要启动,GPU端计算节点的标志位结果数组d_Visited_Island[i]=m,表示第i号计算节点属于第m号电气岛,将各电气岛包含的计算节点序号和物理节点序号,保存在SystemMap中。
作为优选方案,对电网调度控制***电网模型进行图论抽象,得到CPU端的物理节点的压缩邻接数组h_Adj1,h_Adj1Index,h_Adj2,h_Adj2Index,具体步骤如下:
物理节点存储于PhysicalNodeMap中,共有VertexNum个物理节点,每个物理节点均包含无阻抗邻接数组Adjlist1和有阻抗邻接数组Adjlist2,PhysicalNodeMap为物理节点与序号关系的映射表;
物理节点的搜索方法为,遍历全体电气元件,检查其两端电气连接点唯一标识,若尚未包含在PhysicalNodeMap中,则将该标识与该物理节点对应的序号建立映射,存入PhysicalNodeMap中;
无阻抗支路的搜索方法为,遍历全体隔离开关和断路器,根据其两端电气连接点唯一标识,根据PhysicalNodeMap中映射,将两端物理节点对应的序号,分别填入对方的无阻抗邻接数组Adjlist1中;
有阻抗支路的搜索方法为,遍历全体变压器、输电线路和串联补偿器,根据其两端电气连接点唯一标识,根据PhysicalNodeMap中映射,将两端物理节点对应的序号,分别填入对方的有阻抗邻接数组Adjlist2中;
全网物理节点的第一压缩邻接数组h_Adj1,它是将每个物理节点的无阻抗邻接数组Adjlist1,根据其序号递增的顺序首尾相连;h_Adj1的索引数组h_Adj1Index记录每个物理节点的无阻抗邻接数组Adjlist1在h_Adj1中的起止位置;
全网物理节点的第二压缩邻接数组h_Adj2,它是将每个物理节点的有阻抗邻接数组Adjlist2,根据其序号递增的顺序首尾相连;h_Adj2的索引数组h_Adj2Index记录每个物理节点的Adjlist2在h_Adj2中的起止位置。
一种基于GPU加速的电网拓扑分析高性能计算装置,包括如下模块:
电网模型转换模块:CPU对电网调度控制***电网模型进行图论抽象,得到CPU端的压缩邻接数组h_Adj1,h_Adj2,h_Adj1代表全网物理节点的第一压缩邻接数组,h_Adj2代表全网物理节点的第二压缩邻接数组;
第一内核函数调用模块:GPU调用内核函数Topo_Kernel_1<BlockNum,ThreadNum>,将CPU端全网物理节点的第一压缩邻接数组h_Adj1传到GPU端全网物理节点的第一压缩邻接数组d_Adj1,根据GPU端物理节点的标志位前驱数组d_Frontier[d_Adj1[i]]=1,GPU端物理节点的标志位结果数组d_Visited[i]=m,将各计算节点包含的物理节点序号,保存在CalculationNodeMap中,再根据CPU端全网物理节点的第二压缩邻接数组h_Adj2,得到CPU端计算节点的压缩邻接数组h_Adj_Island;d_Frontier[d_Adj1[i]]=1表示在下一次启动时,d_Adj1[i]号物理节点需要启动,d_Visited[i]=m表示第i个物理节点属于m号计算节点,BlockNum表示同时启动的线程块数,ThreadNum表示每一个线程块内,同时启动的线程数;
第二内核函数调用模块:GPU调用内核函数Topo_Kernel_2<BlockNum,ThreadNum>,将CPU端计算节点的压缩邻接数组h_Adj_Island传到GPU端计算节点的压缩邻接数组d_Adj_Island,根据GPU端计算节点的标志位前驱数组d_Frontier_Island[d_Adj_Island[i]]=1,GPU端计算节点的标志位结果数组d_Visited_Island[i]=m,将各电气岛包含的计算节点序号和物理节点序号,保存在SystemMap中,d_Frontier_Island[d_Adj_Island[i]]=1表示在下一次启动时,d_Adj_Island[i]号节点需要启动,d_Visited_Island[i]=m,表示第i号计算节点属于第m号电气岛,SystemMap为电气岛与序号关系的映射表。
作为优选方案,Topo_Kernel_1<BlockNum,ThreadNum>的计算流程如下:
(2.1)CPU端设置物理节点的标志位d_Frontier前驱数组,d_Visited结果数组的初始值分别为0,-1,其中,d_Frontier前驱数组的值为0代表本次执行该线程不启动,d_Visited结果数组的值为-1 代表该物理节点还未被访问;
(2.2)CPU端,当第k个物理节点h_Visited[k]=-1时,表示第k个物理节点的未被访问,令其h_Frontier[k]=1,表示第k个物理节点本次执行线程启动,并将h_Frontier和h_Visited传往GPU,替换前驱数组d_Frontier和结果数组d_Visited;
(2.3)GPU运算平台CUDA自动为每个线程分配线程块索引blockID和线程块中的线程索引threadID;
(2.4)GPU上,将blockID和threadID分别赋值给变量bid和tid,通过bid和tid来索引GPU上bid号线程块中的tid号线程,GPU并行采用大量线程同时启动的方法,即bid取值范围为0到BlockNum,tid取值范围为0到ThreadNum,下述过程在每根线程上同时发生;
(2.5) GPU第bid号线程块中的tid号线程用于更新***中的第bid*ThreadNum+tid个物理节点的标志位d_Frontier前驱数组,d_Visited结果数组,以及遍历该物理节点的压缩邻接数组;设j=bid*ThreadNum+tid,全体线程中,仅有满足前驱数组d_Frontier[j]=1的线程继续执行,其他线程均关闭,等待下一次启动;
(2.6)GPU端启动的线程中,第j个物理节点的第一压缩邻接数组起始位为d_Adj1Index[j],终止位为d_Adj1Index[j+1],表示第j个物理节点的第一压缩邻接数组的值依次为d_Adj1[d_Adj1Index[j]]、d_Adj1[d_Adj1Index[j]+1]、d_Adj1[d_Adj1Index[j]+2]……,d_Adj1[d_Adj1Index[j+1]],第j个物理节点的前驱数组为d_Frontier[j],结果数组为d_Visited[j];
(2.7)第bid号线程块的tid号线程中,变量i从d_Adj1Index[j]递增到d_Adj1Index[j+1],当且仅当d_Visited[i]=-1时,代表结果数组尚未被访问过,令d_Frontier[d_Adj1[i]]=1,表示在下一次启动时,d_Adj1[i]号节点需要启动,d_Visited[i]=m,表示该物理节点属于第m号计算节点;
(2.8)在GPU端,调用设备端函数Is_F_Empty(),变量k对d_Frontier前驱数组进行遍历,是否存在d_Frontier[k]=1,如有,再次启动全部线程,回到步骤(2.4),如果不存在d_Frontier[k]=1,表示第m号计算节点划分完成,令m自加1;
(2.9)将计算后的d_Visited结果数组从GPU端读回CPU端并存入保存全部物理节点归属于具体计算节点信息的结果数组h_Visited中;
(2.10)在CPU端,变量k从0增加到VertexNum,是否有h_Visited[k]=-1,如存在,说明尚有物理节点未被划分,回到步骤(2.2)继续进行循环,若不存在,说明全网物理节点均划分到相应的计算节点,进入步骤(2.11);
(2.11)在CPU端,将每个计算节点包含的物理节点的序号存储到CalculationNodeMap,得到CalculationNodeCounter个计算节点。
(2.12)在CPU端,变量i按顺序遍历CalculationNodeCounter,对于第i个计算节点包含的第k号物理节点,其物理节点的第二压缩邻接数组的起始位为h_Adj2Index[k],终止位为h_Adj2Index[k+1],对于第k号物理节点的第二压缩邻接数组的第j位的值h_Adj2[j],令计算节点的压缩邻接数组h_Adj_Island[p]=h_Visited[h_Adj2[j]],表示第i个计算节点与第h_Adj2[j]号物理节点所属的[h_Visited[h_Adj_2[j]]号计算节点相连,p为一个递增的指针,指向h_Adj_Island的末尾;当第i个计算节点的压缩邻接数组生成完后,令计算节点的压缩邻接数组的索引数组h_AdjIndex_Island[i+1]=p。
作为优选方案,所述ThreadNum设置为1024,线程块数量BlockNum =(VertexNum-1)/ ThreadNum+1。
作为优选方案,Topo_Kernel_2<BlockNum,ThreadNum>的计算流程如下,
(3.1)CPU端设置计算节点的标志位d_Frontier_Island前驱数组,d_Visited_Island结果数组的初始值分别为0,-1,其中,d_Frontier_Island前驱数组的值为0代表本次执行该线程不启动,d_Visited_Island结果数组的值为-1 代表该计算节点还未被访问;
(3.2)CPU端,当第k个计算节点h_Visited_Island[k]=-1时,令其h_Frontier_Island[k]=1,表示第k个计算节点本次执行线程启动,并将h_Frontier_Island和h_Visited_Island传往GPU,替换前驱数组d_Frontier_Island和结果数组d_Visited_Island;
(3.3)GPU运算平台CUDA自动为每个线程分配线程块索引blockID和线程块中的线程索引threadID;
(3.4)GPU上,将blockID和threadID分别赋值给变量bid和tid,通过bid和tid来索引GPU上bid号线程块中的tid号线程,GPU并行采用大量线程同时启动的方法,即bid取值范围为0到BlockNum,tid取值范围为0到ThreadNum,下述过程在每根线程上同时发生;
(3.5) GPU第bid号线程块中的tid号线程负责更新***中的第bid*ThreadNum+tid个计算节点的标志位d_Frontier_Island前驱数组,d_Visited_Island结果数组,以及遍历该计算节点的压缩邻接数组;设j=bid*ThreadNum+tid,全体线程中,仅有满足前驱数组d_Frontier_Island[j]=1的线程继续执行,其他线程均关闭,等待下一次启动;
(3.6)GPU端启动的线程中,第j个计算节点的压缩邻接数组起始位为d_AdjIndex_Island [j],终止位为d_AdjIndex_Island [j+1],表示第j个计算节点的压缩邻接数组的值依次为d_Adj_Island [d_AdjIndex_Island [j]],d_Adj_Island [d_AdjIndex_Island[j]+1]……,d_Adj_Island [d_AdjIndex_Island [j+1]],第j个计算节点的前驱数组为d_Frontier_Island [j],结果数组为d_Visited_Island [j];
(3.7)第bid号线程块的tid号线程中,变量i从d_AdjIndex_Island[j]递增到d_AdjIndex_Island[j+1],当且仅当d_Visited_Island[i]=-1时,代表结果数组尚未被访问过,令d_Frontier_Island[d_Adj_Island[i]]=1,表示在下一次启动时,d_Adj_Island[i]号节点需要启动,d_Visited_Island[i]=m,表示该计算节点属于第m号电气岛;
(3.8)在GPU端,调用设备端函数Is_F_Empty(),变量k对d_Frontier_Island前驱数组进行遍历,是否存在d_Frontier_Island[k]=1,如有,再次启动全部线程,回到步骤(3.4),如果不存在d_Frontier_Island[k]=1,说明第m号电气岛划分完成,令m自加1;
(3.9)将计算后的d_Visited_Island结果数组从GPU端读回CPU端并存入保存全部计算节点归属于具体电气岛信息的结果数组h_Visited_Island中;
(3.10)在CPU端,变量k从0增加到CalculationNodeCounter,检查是否有h_Visited_Island[k]=-1,如存在,说明尚有计算节点未被划分,回到步骤(3.2)继续进行循环,若不存在,说明全网计算节点均划分完成,进入步骤(3.11);
(3.11)在CPU端,将每个电气岛包含的计算节点的序号存储到SystemMap中。
作为优选方案,所述ThreadNum设置为128,BlockNum =(CalculationNodeCounter-1)/ ThreadNum+1。
有益效果:本发明提供的一种基于GPU加速的电网拓扑分析高性能计算方法,根据电网模型分层分区的特点,以及电网计算需求的抽象特性,对电网中各类元器件进行抽象建模,并将电网信息保存到***内存中,在使CPU和GPU能够共享使用数据的同时,保持了CPU与GPU不同设备间数据格式的一致性,保证了并行网络拓扑分析的执行效率和稳定性。
将GPU通用并行计算技术应用到电网网络拓扑分析中,提高了电网网络拓扑分析的执行效率,为大规模并联电网的在线分析计算提供了实时性的支持,以便在后续计算应用时能更及时地得到电网结构的实时状态。
具体实施方式
下面结合附图对本发明作更进一步的说明。
本发明为大规模并联电网的在线分析计算提供构建电网拓扑所需要的物理节点、计算节点和电气岛,以便本领域技术人员在后续计算应用时能更及时地得到电网拓扑结构的实时状态。电网拓扑结构是电网分析计算的基础,拓扑分析模块是在线***分析计算中的基础模块,承担着为电网其他分析模块提供计算基础条件的任务,其正确性和实时性是大电网在线分析应用的实用性的重要保障。因此,实现高效的拓扑分析算法,能够提高电网在线分析应用的性能,有助于电网的安全稳定运行。GPU并行计算是一种新颖的通用计算实现方法,本发明针对电网的实际属性和运行特性,实现了一种基于GPU加速的电网拓扑分析高性能计算方法,提高了大规模电网拓扑分析的执行效率,从而提高大电网在线应用的实用性水平。
如图1所示,本发明提供一种基于GPU加速的电网拓扑分析高性能计算方法,包括以下步骤:
步骤1:CPU中读取电网调度控制***电网模型及全体数据,对电网调度控制***电网模型进行图论抽象,得到CPU端的压缩邻接数组h_Adj1,h_Adj1Index,h_Adj2,h_Adj2Index,h_Adj1代表全网物理节点的第一压缩邻接数组,h_Adj1Index代表h_Adj1的索引数组,h_Adj2代表全网物理节点的第二压缩邻接数组,h_Adj2Index代表h_Adj2的索引数组,为并行拓扑分析做准备。
所述步骤1中,读取电网调度控制***采用的模型作为电网模型。所述电网模型中模型对象包括基准值、断路器、刀闸、母线、同步发电机、负荷、变压器、并联补偿器、串联补偿器、交流线段。
所述断路器、刀闸、母线、同步发电机、负荷、变压器、并联补偿器、串联补偿器、交流线段称为电气元件,用于描述电网中实际电气设备;
基准值及各电气元件包含的电压等级、归属辖区、唯一标识、实时量测信息项目,用于保存电网模型的实时数据信息,仅服务于拓扑分析后续的计算模块,不涉及拓扑分析计算。
物理节点是电气元件上包含的实际电气连接点。
无阻抗支路是隔离开关和断路器上包含的物理节点的邻接关系。
有阻抗支路是变压器、输电线路和串联补偿器上包含的物理节点的邻接关系。
在CPU端设置四个压缩邻接数组,分别为h_Adj1,h_Adj1Index,h_Adj2,h_Adj2Index,分别对应在GPU中的压缩邻接数组为d_Adj1,d_Adj1Index,d_Adj2,d_Adj2Index。在GPU编程中,由于CPU与GPU访问不同的内存空间,为防止混淆,规定如下命名方式,对于CPU端,即主机端host访问的数组,以小写字母h为前缀,对于GPU端,即设备端device访问的数组,以小写字母d为前缀。
对电网调度控制***电网模型进行图论抽象,得到CPU端的物理节点的压缩邻接数组h_Adj1,h_Adj1Index,h_Adj2,h_Adj2Index,具体步骤如下:
物理节点存储于PhysicalNodeMap中,共有VertexNum个物理节点,每个物理节点均包含无阻抗邻接数组Adjlist1和有阻抗邻接数组Adjlist2,PhysicalNodeMap为物理节点与序号关系的映射表。
物理节点的搜索方法为,遍历全体电气元件,检查其两端电气连接点唯一标识,若尚未包含在PhysicalNodeMap中,则将该标识与该物理节点对应的序号建立映射,存入PhysicalNodeMap中。
无阻抗支路的搜索方法为,遍历全体隔离开关和断路器,根据其两端电气连接点唯一标识,根据PhysicalNodeMap中映射,将两端物理节点对应的序号,分别填入对方的无阻抗邻接数组Adjlist1中。
有阻抗支路的搜索方法为,遍历全体变压器、输电线路和串联补偿器,根据其两端电气连接点唯一标识,根据PhysicalNodeMap中映射,将两端物理节点对应的序号,分别填入对方的有阻抗邻接数组Adjlist2中。
全网物理节点的第一压缩邻接数组h_Adj1,它是将每个物理节点的无阻抗邻接数组Adjlist1,根据其序号递增的顺序首尾相连。h_Adj1的索引数组h_Adj1Index记录每个物理节点的无阻抗邻接数组Adjlist1在h_Adj1中的起止位置。
全网物理节点的第二压缩邻接数组h_Adj2,它是将每个物理节点的有阻抗邻接数组Adjlist2,根据其序号递增的顺序首尾相连。h_Adj2的索引数组h_Adj2Index记录每个物理节点的Adjlist2在h_Adj2中的起止位置。
步骤2:GPU中调用并行网络拓扑分析内核函数Topo_Kernel_1;
并行网络拓扑分析内核函数被定义为Topo_Kernel_1<BlockNum,ThreadNum>,其中变量BlockNum和ThreadNum,分别为GPU多线程运行参数。其中,BlockNum表示该内核函数在GPU启动时,同时启动的线程块数,ThreadNum表示每一个线程块内,同时启动的线程数。对于一个GPU函数而言,尖括号内包含的参数规定了一共启动的线程总数为BlockNum*ThreadNum,该值越大,一般意味着同时工作的线程数就越多,并行加速效果越好。对于Topo_Kernel_1,其线程块大小ThreadNum固定为1024,线程块数量BlockNum =(VertexNum-1)/ ThreadNum+1。调用并行网络拓扑分析内核函数Topo_Kernel_1<BlockNum,ThreadNum>,将CPU端全网物理节点的第一压缩邻接数组h_Adj1传到GPU端全网物理节点的第一压缩邻接数组d_Adj1,根据GPU端物理节点的标志位前驱数组d_Frontier[d_Adj1[i]]=1,表示在下一次启动时,d_Adj1[i]号物理节点需要启动,GPU端物理节点的标志位结果数组d_Visited[i]=m,表示第i个物理节点属于m号计算节点,将各计算节点包含的物理节点序号,保存在CalculationNodeMap中,再根据CPU端全网物理节点的第二压缩邻接数组h_Adj2,得到CPU端计算节点的压缩邻接数组h_Adj_Island。
Topo_Kernel_1<BlockNum,ThreadNum>的计算流程如下:
(2.1)CPU端设置物理节点的标志位d_Frontier前驱数组,d_Visited结果数组的初始值分别为0,-1,其中,d_Frontier前驱数组的值为0代表本次执行该线程不启动,d_Visited结果数组的值为-1 代表该物理节点还未被访问;
(2.2)CPU端,当第k个物理节点h_Visited[k]=-1时,表示第k个物理节点的未被访问,令其h_Frontier[k]=1,表示第k个物理节点本次执行线程启动,并将h_Frontier和h_Visited传往GPU,替换前驱数组d_Frontier和结果数组d_Visited;
(2.3)GPU运算平台CUDA(Compute Unified Device Architecture)自动为每个线程分配线程块索引blockID和线程块中的线程索引threadID;
(2.4)GPU上,将blockID和threadID分别赋值给变量bid和tid,通过bid和tid来索引GPU上bid号线程块中的tid号线程,GPU并行采用大量线程同时启动的方法,即bid取值范围为0到BlockNum,tid取值范围为0到ThreadNum,下述过程在每根线程上同时发生;
(2.5) GPU第bid号线程块中的tid号线程用于更新***中的第bid*ThreadNum+tid个物理节点的标志位d_Frontier前驱数组,d_Visited结果数组,以及遍历该物理节点的压缩邻接数组。设j=bid*ThreadNum+tid,全体线程中,仅有满足前驱数组d_Frontier[j]=1的线程继续执行,其他线程均关闭,等待下一次启动。
(2.6)GPU端启动的线程中,第j个物理节点的第一压缩邻接数组起始位为d_Adj1Index[j],终止位为d_Adj1Index[j+1],表示第j个物理节点的第一压缩邻接数组的值依次为d_Adj1[d_Adj1Index[j]]、d_Adj1[d_Adj1Index[j]+1]、d_Adj1[d_Adj1Index[j]+2]……,d_Adj1[d_Adj1Index[j+1]],第j个物理节点的前驱数组为d_Frontier[j],结果数组为d_Visited[j];
(2.7)第bid号线程块的tid号线程中,变量i从d_Adj1Index[j]递增到d_Adj1Index[j+1],当且仅当d_Visited[i]=-1时,代表结果数组尚未被访问过,令d_Frontier[d_Adj1[i]]=1,表示在下一次启动时,d_Adj1[i]号节点需要启动,d_Visited[i]=m,表示该物理节点属于第m号计算节点;
(2.8)在GPU端,调用设备端函数Is_F_Empty(),该函数流程为,变量k对d_Frontier前驱数组进行遍历,是否存在d_Frontier[k]=1,如有,再次启动全部线程,回到步骤(2.4),如果不存在d_Frontier[k]=1,说明第m号计算节点划分完成,令m自加1;
(2.9)将已经形成的d_Visited结果数组从GPU端读回CPU端并存入保存全部物理节点归属于具体计算节点信息的结果数组h_Visited中;
(2.10)在CPU端,变量k从0增加到VertexNum,是否有h_Visited[k]=-1,如存在,说明尚有物理节点未被划分,回到步骤(2.2)继续进行循环,若不存在,说明全网物理节点均划分到相应的计算节点,进入步骤(2.11);
(2.11)在CPU端,将每个计算节点包含的物理节点的序号存储到CalculationNodeMap,得到CalculationNodeCounter个计算节点。
(2.12)在CPU端,变量i按顺序遍历CalculationNodeCounter,对于第i个计算节点包含的第k号物理节点,其物理节点的第二压缩邻接数组的起始位为h_Adj2Index[k],终止位为h_Adj2Index[k+1],对于第k号物理节点的第二压缩邻接数组的第j位的值h_Adj2[j],令计算节点的压缩邻接数组h_Adj_Island[p]=h_Visited[h_Adj2[j]],表示第i个计算节点与第h_Adj2[j]号物理节点所属的[h_Visited[h_Adj_2[j]]号计算节点相连,p为一个递增的指针,指向h_Adj_Island的末尾;当第i个计算节点的压缩邻接数组生成完后,令计算节点的压缩邻接数组的索引数组h_AdjIndex_Island[i+1]=p。
h_Adj_Island代表全网计算节点的压缩邻接数组,h_AdjIndex_Island代表h_Adj_Island的索引数组,
内核函数Topo_Kernel_1<BlockNum,ThreadNum>在一个小型无向图上的执行原理如图3所示:
CPU调用内核函数时,已预先搜索到第一个未被访问的物理节点0号节点,并令d_Frontier[0]=1(对应步骤2.2)。内核函数Topo_Kernel_1启动全部线程(对应步骤2.3及2.4),但仅有0号线程运行(对应步骤2.5),0号线程根据d_Adj1的内容,顺序地访问3号、4号、5号节点(对应步骤2.6),令d_Frontier[0]=0,d_Frontier[3]=d_Frontier[4]=d_Frontier[5]=1,d_Visited[3]=d_Visited[4]=d_Visited[5]=0(对应步骤2.7);
由于d_Frontier数组不全为0,再次启动全体线程(对应步骤2.8),有3号、4号、5号线程运行(对应步骤2.5),它们分别根据d_Adj1的内容,分别访问7号、8号、9号节点(对应步骤2.6),令d_Frontier[3]=d_Frontier[4]=d_Frontier[5]=0,d_Frontier[7]=d_Frontier[8]=d_Frontier[9]=1,d_Visited[7]=d_Visited[8]=d_Visited[9]=0(对应步骤2.7);
根据步骤2.8,继续上述步骤2次,直到d_Frontier在所有线程运行结束后仍然全为0,进入步骤2.10,此时仍有d_Visited[2]=-1,再次回到步骤2.2,对2号物理节点所属计算节点进行划分。本次划分完成时,无向图中所有物理节点均被划分,不再重新调用内核函数,启动步骤2.11和步骤2.12进行数据扫描存储。
步骤3:实施并行***拓扑分析;
用于实施并行***拓扑分析的内核函数被称为并行广度优先搜索算法内核函数,定义为Topo_Kernel_2<BlockNum,ThreadNum>,其线程块大小ThreadNum固定为128,线程块数量BlockNum =(CalculationNodeCounter-1)/ ThreadNum+1。
调用一次并行广度优先搜索算法内核函数Topo_Kernel_2<BlockNum,ThreadNum>,将CPU端计算节点的压缩邻接数组h_Adj_Island传到GPU端计算节点的压缩邻接数组d_Adj_Island,根据GPU端计算节点的标志位前驱数组d_Frontier_Island[d_Adj_Island[i]]=1,表示在下一次启动时,d_Adj_Island[i]号节点需要启动,GPU端计算节点的标志位结果数组d_Visited_Island[i]=m,表示第i号计算节点属于第m号电气岛,将各电气岛包含的计算节点序号和物理节点序号,保存在SystemMap中。
Topo_Kernel_2<BlockNum,ThreadNum>的计算流程如下,
(3.1)CPU端设置计算节点的标志位d_Frontier_Island前驱数组,d_Visited_Island结果数组的初始值分别为0,-1,其中,d_Frontier_Island前驱数组的值为0代表本次执行该线程不启动,d_Visited_Island结果数组的值为-1 代表该计算节点还未被访问;
(3.2)CPU端,当第k个计算节点h_Visited_Island[k]=-1时,令其h_Frontier_Island[k]=1,表示第k个计算节点本次执行线程启动,并将h_Frontier_Island和h_Visited_Island传往GPU,替换前驱数组d_Frontier_Island和结果数组d_Visited_Island;
(3.3)GPU运算平台CUDA(Compute Unified Device Architecture)自动为每个线程分配线程块索引blockID和线程块中的线程索引threadID;
(3.4)GPU上,将blockID和threadID分别赋值给变量bid和tid,通过bid和tid来索引GPU上bid号线程块中的tid号线程,GPU并行采用大量线程同时启动的方法,即bid取值范围为0到BlockNum,tid取值范围为0到ThreadNum,下述过程在每根线程上同时发生;
(3.5) GPU第bid号线程块中的tid号线程负责更新***中的第bid*ThreadNum+tid个计算节点的标志位d_Frontier_Island前驱数组,d_Visited_Island结果数组,以及遍历该计算节点的压缩邻接数组。设j=bid*ThreadNum+tid,全体线程中,仅有满足前驱数组d_Frontier_Island[j]=1的线程继续执行,其他线程均关闭,等待下一次启动。
(3.6)GPU端启动的线程中,第j个计算节点的压缩邻接数组起始位为d_AdjIndex_Island [j],终止位为d_AdjIndex_Island [j+1],表示第j个计算节点的压缩邻接数组的值依次为d_Adj_Island [d_AdjIndex_Island [j]],d_Adj_Island [d_AdjIndex_Island[j]+1]……,d_Adj_Island [d_AdjIndex_Island [j+1]],第j个计算节点的前驱数组为d_Frontier_Island [j],结果数组为d_Visited_Island [j];
(3.7)第bid号线程块的tid号线程中,变量i从d_AdjIndex_Island[j]递增到d_AdjIndex_Island[j+1],当且仅当d_Visited_Island[i]=-1时,代表结果数组尚未被访问过,令d_Frontier_Island[d_Adj_Island[i]]=1,表示在下一次启动时,d_Adj_Island[i]号节点需要启动,d_Visited_Island[i]=m,表示该计算节点属于第m号电气岛;
(3.8)在GPU端,调用设备端函数Is_F_Empty(),该函数流程为,变量k对d_Frontier_Island前驱数组进行遍历,是否存在d_Frontier_Island[k]=1,如有,再次启动全部线程,回到步骤(3.4),如果不存在d_Frontier_Island[k]=1,说明第m号电气岛划分完成,令m自加1;
(3.9)将已经形成的d_Visited_Island结果数组从GPU端读回CPU端并存入保存全部计算节点归属于具体电气岛信息的结果数组h_Visited_Island中;
(3.10)在CPU端,变量k从0增加到CalculationNodeCounter,检查是否有h_Visited_Island[k]=-1,如存在,说明尚有计算节点未被划分,回到步骤(3.2)继续进行循环,若不存在,说明全网计算节点均划分完成,进入步骤(3.11);
(3.11)在CPU端,将每个电气岛包含的计算节点的序号存储到SystemMap中。
步骤3完成后,由电网断面文件,已经生成用于后续应用层计算的计算节点,划分结果保存在h_Visited数组中,已生成反映电网拓扑结构的电气岛,划分结果保存在h_Visited_Island中,经GPU加速的电网拓扑分析完成。
如图2所示,根据电网模型分层的特性,拓扑分析方法形成具有多层次的拓扑分析模型,拓扑分析模型包含物理节点、计算节点、电气岛、无阻抗支路和有阻抗支路。
物理节点存储于PhysicalNodeMap中,共有VertexNum个物理节点,每个物理节点均包含无阻抗邻接数组Adjlist1和有阻抗邻接数组Adjlist2,PhysicalNodeMap为物理节点与序号关系的映射表。
计算节点是物理节点通过无阻抗支路相连形成的,在厂站拓扑分析中形成分布在全网的大量连通片,存储于CalculationNodeMap中,CalculationNodeMap为计算节点与序号关系的映射表;
电气岛是计算节点通过有阻抗支路相连形成的,在电网拓扑分析中往往形成一个覆盖全网的电气岛,电气岛存储于SystemMap中,SystemMap为电气岛与序号关系的映射表。
实施例
利用智能电网调度***断面文件对实际电网进行测试。测试电网模型为网调级别电网,包括:线路2297条,机组338个,负荷78个,变压器1769个,并联补偿器621个,串联补偿器9个,断路器8574个,刀闸22126个。拓扑分析后计算节点1736个,主岛计算节点1345个,包含物理节点22991个。
测试平台软硬件配置如下表:
序号 |
名称 |
版本 |
备注 |
1 |
Windows操作*** |
Window10 专业版(64位) |
|
2 |
CUDA |
CUDA 10.1 |
|
3 |
CPU |
Intel i9-9900K |
|
4 |
GPU |
NVIDIA TITAN RTX |
|
测试结果如下表:
|
步骤1耗时(ms) |
步骤2耗时(ms) |
步骤3耗时(ms) |
串行网络拓扑分析 |
20.4075 |
9.3576 |
4.3466 |
并行网络拓扑分析 |
14.8466 |
0.4654 |
0.466688 |
本方法利用电网模型的特点,提出一种基于GPU加速的电网拓扑分析高性能计算方法,提高了网络拓扑分析计算速度。以上测试结果表明,对于较大规模电网, GPU加速的网络拓扑分析计算耗时明显低于传统方法,能够更加快速的为大电网在线分析计算提供可靠拓扑结构结果,供后序计算步骤使用,为电网智能调度提供支撑。
本领域内的技术人员应明白,本申请的实施例可提供为方法、***、或计算机程序产品。因此,本申请可采用完全硬件实施例、完全软件实施例、或结合软件和硬件方面的实施例的形式。而且,本申请可采用在一个或多个其中包含有计算机可用程序代码的计算机可用存储介质(包括但不限于磁盘存储器、CD-ROM、光学存储器等)上实施的计算机程序产品的形式。
本申请是参照根据本申请实施例的方法、设备(***)、和计算机程序产品的流程图和/或方框图来描述的。应理解可由计算机程序指令实现流程图和/或方框图中的每一流程和/或方框、以及流程图和/或方框图中的流程和/或方框的结合。可提供这些计算机程序指令到通用计算机、专用计算机、嵌入式处理机或其他可编程数据处理设备的处理器以产生一个机器,使得通过计算机或其他可编程数据处理设备的处理器执行的指令产生用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的装置。
这些计算机程序指令也可存储在能引导计算机或其他可编程数据处理设备以特定方式工作的计算机可读存储器中,使得存储在该计算机可读存储器中的指令产生包括指令装置的制造品,该指令装置实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能。
这些计算机程序指令也可装载到计算机或其他可编程数据处理设备上,使得在计算机或其他可编程设备上执行一系列操作步骤以产生计算机实现的处理,从而在计算机或其他可编程设备上执行的指令提供用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的步骤。
以上所述仅是本发明的优选实施方式,应当指出:对于本技术领域的普通技术人员来说,在不脱离本发明原理的前提下,还可以做出若干改进和润饰,这些改进和润饰也应视为本发明的保护范围。