zoukankan      html  css  js  c++  java
  • 中科大算法分析与设计分布式算法复习知识点

    一、分布式算法

    1.1 导论

    并行处理与分布式处理的区别

    • 并行处理目标:使用所有处理器执行一个大任务。
    • 分布式处理具有更高程度的不确定性和行为的独立性,每个处理器都有自己独立的任务。

    分布式系统作用

    • 共享资源
    • 改善性能
    • 提高可靠性

    模型:

    • 异步共享存储模型:用于紧耦合机器
    • 异步msg传递模型:用于松散耦合机器及广域网
    • 同步msg传递模型:msg延迟上界已知,系统执行划分为轮执行,是异步系统的特例

    1.2 消息传递中的基本算法

    每个处理器\(p_i\)可以模型化为一个具有状态集\(Q_i\)的状态机

    初始状态\(Q_i\)包含一个特殊的初始状态子集,每个inbuf必须为空,outbuf不一定为空。

    转换函数:将可访问状态的inbuf转换到outbuf

    配置:分布式系统上某点整个算法的全局状态

    事件计算事件传递事件

    执行:配置和事件交错的序列。

    需满足安全性条件和活跃性条件。

    1. 安全性:某个性质在每次执行的每个可达配置里都成立。“坏事从不发生”

    2. 活跃性:某个性质在每次执行的某些可达配置里成立。“最终某个好事发生”

    满足安全性条件称为执行。同时满足活跃性条件称为容许执行

    1.2.1 转移系统与安全性和活跃性

    转移系统\(三元组 Triple \ S=(C,\rightarrow,I)\)\(C\)是配置集,\(I\)是初始配置的一个子集,\(\rightarrow\)是配置集上的二元转移关系。

    可达\(\exist \ 序列 \gamma_0 \rightarrow \gamma_1 \rightarrow \cdots \rightarrow \gamma_k = \delta,且\forall 0 \le i \le k-1,\gamma_i \rightarrow \gamma_{i+1},则称\delta是可达的\)

    安全性\(S=(C,\rightarrow,I),断言/性质P总是成立\)

    \(\{P\} \rightarrow \{Q\}:\forall \gamma \rightarrow \delta, if \ P(\gamma),then \ Q(\delta)\),即如果P在转移前成立,则Q在转移后成立

    定义:\(P是S的不变式,\forall \gamma \in I,P(\gamma)成立且\{P\}\rightarrow\{P\},P总是成立\),P为安全性条件

    定理:如果P是S的不变式,那么对S的每次执行的每一配置P都成立

    活跃性:在算法的每次执行的某些配置中,P为真,且最终P为真。

    判断方法:

    • 范函数
    • 无死锁 / 系统正常终止

    范函数\(转移系统S和断言P,f:配置集C\rightarrow良基集\omega\)

    良基集\(偏序集(\omega,<)是良基的,当且仅当不存在无穷递减序列,即存在最小值\)

    1.2.2 系统

    异步系统

    异步msg传递时间和一个处理器的两个相继步骤之间的时间无上界

    执行片段:一个有限或无限的序列,由配置事件交替组成

    执行:从初始配置开始的执行片段

    调度执行中的事件序列

    容许执行:某个处理器有无限个计算事件(指处理器没有出错,并不是无限步),每个发送的msg都最终被传递。

    同步系统

    处理器按轮执行,一轮里,每个处理器可以发送一个msg到邻居,每个处理器一接受到msg就计算。

    :配置和事件序列可以划分为不相交的轮,每轮由一个传递事件一个计算事件组成。

    同步系统与异步系统的区别:

    1. 无错的同步系统中,算法的执行只取决于初始配置
    2. 异步系统中,算法可能有不同的执行(不代表不同的结果)

    1.2.3 复杂性度量

    消息复杂度:所有容许执行上发送消息总数的最大值

    时间复杂度

    • 同步系统:最大轮数
    • 异步系统:所有计时容许执行中直到终止的最大时间

    1.2.4 生成树上的广播和敛播

    生成树ST:具有共同顶点不出现回路的子图。

    最小生成树MST:所有边权值和最小的生成树。

    广播

    基本步骤

    1. \(p_r\)发送\(M\)给所有的孩子。
    2. 某节点收到父节点的\(M\)时,发送\(M\)给自己的所有孩子。
    upon receiving no msg:
    	if i=r then
            send <M> to all children;
    		terminates;
    upon receiving <M> from P_j:
    	send <M> to all children;
    	terminates;
    

    消息复杂度\(O(n)\)

    时间复杂度\(O(h),h为生成树高度\)

    敛播

    基本步骤

    1. 每个叶子节点发送消息给双亲
    2. 每个非叶节点等待所有孩子的消息,之后再发消息给双亲

    消息复杂度\(O(n)\)

    时间复杂度\(O(h),h为生成树高度\)

    1.2.5 构造生成树

    Flooding算法

    消息复杂度:\(O(2m-(n-1))\)

    事件复杂度:\(O(D),D为网直径\)

    基本思想

    1. 根节点发送消息\(M\)给所有邻居

    2. \(P_i\)收到来自\(P_j\)的消息\(M\)且是第一次收到消息\(M\)时,\(P_i\)发送\(<parent>\)\(P_j\)\(P_i\)向其他向自己发送消息\(M\)的节点发送\(<reject>\)\(P_i\)\(P_j\)以外的邻居发送消息\(M\)

    3. \(P_i\)收到\(P_j的<parent>\)消息,则表明\(P_i是P_j的父节点\)

    Code for Pi (0<=i<=n-1)
    初值:parent=nil;集合children和other均为空集
    
    upon receiving no message:
        if i=r and parent=nil then { //根尚未发送M
        	send M to all neighbors;
        	parent:=i;} //根的双亲置为自己
    upon receiving M from neighbor pj:
        if parent=nil then { //pi此前未收到过M,M是pi收到的第1个msg
        	parent:=j;
        	send <parent> to pj; //pj是pi的双亲
        	send M to all neighbors except pj;
        }else //pj不可能是pi的双亲,pi收到的M不是第1个msg
        	send <reject> to pj;
    upon receiving <parent> from neighbor pj:
        children:=children∪{ j }; //pj是pi的孩子,将j加入孩子集
        if children∪other包含了除parent外的所有邻居 then terminate;
    upon receiving <reject> from neighbor pj:
        other:=other∪{ j }; //将j加入other,通过非树边发送的msg。
        if children∪other包含了除parent外的所有邻居 then terminate
    

    异步模型中,构造以\(p_r\)为根的生成树

    同步模型中,构造的一定是BFS

    在异步系统中无法生成BFS,因为消息传递无上界,最坏可能出现单链。

    1.2.6 指定根构造DFS生成树

    基本思想

    1. 选定根节点\(P_r\),向某一邻接节点发送消息\(M\)
    2. \(P_i\)收到\(P_j\)的消息\(M\)是第一个来自邻接节点的消息时,认定\(P_j\)为其双亲,并向之后给自己发消息\(M\)的节点发送\(<reject>\)
    3. \(P_i\)向未发过消息的邻居中任选一个发送消息\(M\),并等待回复
    4. \(P_i\)向所有邻居发过消息,则\(P_i\)终止
    Code for Pi (0<=i<=n-1)
    初值:
    parent = nil;
    children = Φ;
    unexplored = Pi's neighbors
    
    upon receiving no message:
    	if i=r and parent=nil then { //当Pi为根且未发送M
        	parent:=i; // 将parent设置为自身
         	任意 Pj ∈ unexplored
          	将 Pj 从 unexplored 中删去
        	send M to Pj;}//endif
    upon receiving M from neighbor Pj:
        if parent=nil then { //pi此前未收到过M
        	parent:=j;
           	将 Pj 从 unexplored 中删去
            if unexplored!=Φ then {
               任意 Pk ∈ unexplored
          	将 Pk 从 unexplored 中删去
        	send M to Pk;
            }else send <parent> to parent;
        }else send <reject> to pj; //当Pj已访问过
    upon receiving <parent> or <reject> from neighbor pj:
        if received <parent> then add j to children; // Pj是Pi的孩子
        if unexplored = Φ then { //Pi的邻居均已访问
        	if parent!=i then send <parent> to parent; //Pi非根,返回至双亲
         	terminate; //以Pi为根的DFS子树已构造好
        }else{ //选择Pi未访问过的邻居访问
        	任意 Pk ∈ unexplored
          	将 Pk 从 unexplored 中删去
        	send M to Pk;
        }
    

    消息复杂度,时间复杂度:\(O(m)\)

    1.2.7 不指定根构造DFS生成树

    与领导者选举问题类似,为破对称问题

    基本思想

    1. 每个结点均可自发唤醒,试图构造一根以自己为根的DFS生成树。若两棵DFS树试图链接同一节点(未必同时),选择根ID较大的DFS树加入

    2. 每个结点设置一个leader变量,即为当前DFS树的根ID

    3. 结点自发唤醒时,将自己的leader发送给某一邻居

    Code for Pi (0<=i<=n-1)
    初值:
    parent = nil;
    leader = 0;
    children = Φ;
    unexplored = Pi's neighbors
    
    upon receiving no message: // 自主唤醒
        if parent=nil then { //若非空,则Pi在某子树上,则Pi失去竞选机会
        	leader:=id; parent:=i; // 将parent设置为自身
         	任意 Pj ∈ unexplored
          	将 Pj 从 unexplored 中删去
        	send <leader> to Pj;}//endif
    upon receiving <new_id> from neighbor Pj:
        if leader<new_id then { //将Pi所在树合并到Pj所在树中
        	leader:=new_id; parent:=j;
         	unexplored:=all neighbors of Pi except Pj; //重置未访问邻居集
          	if unexplored!=Φ then { //原Pi所在DFS树修改各自id
               	任意 Pk ∈ unexplored
                	将 Pk 从 unexplored 中删去
        		send <leader> to Pk;
          	}else send <parent> to parent;
        }else if leader=new_id then send <already> to Pj;
    upon receiving <parent> or <already> from neighbor pj:
        if received <parent> then add j to children;
        if unexplored = Φ then { //Pi的邻居均已访问
        	if parent!=i then send <parent> to parent; //Pi非根,返回至双亲
         	else terminate as root of the DFS tree; //以Pi为根的DFS子树已构造好
        }else{ //选择Pi未访问过的邻居访问
        	任意 Pk ∈ unexplored
          	将 Pk 从 unexplored 中删去
        	send <leader> to Pk;
        }
    

    一个具有m条边,n个节点的网络,自发启动的节点由p个,ID值最大的启动时间为t。

    消息复杂度:\(O(pn^2)\)

    时间复杂度:\(O(t+m)\)

    1.3 环上选举算法

    匿名的:环中处理器没有唯一的标识符,每个处理器具有相同的状态机

    一致性、均匀的:不知道处理器的数目

    解释一致性和非一致性:

    算法一:向右转发n步msg,然后终止。 => non_uniform

    算法二:向右转发msg,直到msg发送者收到msg。 => uniform

    在一个匿名的、一致性算法中,所有处理器只有一个状态机。

    在一个匿名的、非一致性算法中,每个n值对应一种状态机。

    • 同步环系统不存在匿名的、一致性的领导者选举算法
    • 异步环系统不存在匿名的领导者选举算法

    1.3.1 异步环

    开调度:在算法A的一次调度中,有一条边上无消息传递,则为开边。

    (开调度未必是容许的调度,是容许执行的一个有限前缀)

    异步环上的选举算法有消息复杂度下界\(O(nlg \ n)\)

    \(O(n^2)的算法\)

    基本思想

    1. 每个处理器发送一个标识符msg给左邻居,然后等着接收右邻居的msg。
    2. 每个处理器收到msg时,若收到的id大于自身,则向左邻居转发。
    3. 若处理器收到自己的标识符id,则宣布自己是leader,并发终止msg给左邻居,然后终止
    4. 若处理器收到终止msg,则向左转发,然后终止

    核心思想:处理器向左邻居发送标识符msg,通过比对id确定leader,只有最大的id消息会回到他自己。

    Code for Pi (0<=i<=n-1)
    初值:asleep=true; id = i;
    
    While (receiving no message) do
      (1) if asleep do
          (1.1) asleep = false
          (1.2) send <id> to left-negihbor
       end if
    End while
    While (receiving <i> from right-neighbor) do
     (1) if id < <i> then send <i> to left-neighbor
           end if
     (2) if id = <i> then
          (2.1) send <Leader,i> to left-neighbor
          (2.2) terminates as Leader
       end if
    End while
    While (receiving <Leader,j> from right-neighbor) do
     (1) send <Leader,j> to left-neighbor
     (2) terminates as non-Leader
    End while
    

    消息复杂度:\(O(n^2)\)

    \(O(nlg(n))\)的算法

    k邻居:据某一处理器距离不超过k的处理器,左边有k个,右边有k个,共有\(2k+1\)个。

    基本思想

    1. 阶段0:每个节点向两个1-邻居发送id消息,若邻居的id小于此消息则回复reply,否则吞没。若一个节点收到两个邻居的reply,则自认为leader,并进入阶段1。
    2. 阶段\(l\):在上一阶段成为leader的处理器,继续发送id消息给\(2^l\)邻居,若收到来自左右两个方向的reply,则自认为leader。
    3. 若收到自己的消息,则终止。

    核心思想:第\(l\)阶段一个处理器试图成为其\(2^l\)-邻居的临时leader。只有在\(l-th\)阶段成为leader的处理器才能继续\((l+1)-th\)阶段。

    Code for Pi (0<=i<=n-1)
    初值:asleep=true;
    
    upon receiving no msg:
          if  asleep then{
          	asleep:=false;//每个结点唤醒后不再进入此代码
           	send <probe,id, 0, 0> to left and right;
          }
    upon receiving <probe, j, l,d> from left_or_right (resp, right):
        if(j=id) then //收到自己id终止,省略发终止msg
          	send <leader,id> to left neighbour;
           	terminate as the leader;
        if(j>id) and (d<2^l) then //向前转发probe msg
        	send <probe, j, l, d+1> to right_or_left (resp, left)
        if(j>id) and (d≥2^l) then //到达最后一个邻居仍未没收
        	send <reply, j, l > to left_or_right (resp, right) // 回答
        // 若j<id, 则没收probe消息
    upon receiving <reply ,j , l> from left (resp, right):
        if j≠id then // 判断是否转发到初始点
        	send <reply, j, l> to right (resp, left); //转发reply
        else //j=id时,Pi已收到一个方向的回答msg
        	if already received <reply, j, l> from right (resp, left) then //也收到另一方向发回的reply
     			send <probe, id, l+1, 0> to left and right; //Pi是phase l的临时leader,继续下一阶段
    upon receiving <leader, idj> from right:
        send <leader, idj> to left;
        terminate as nonleader; 
    

    阶段\(k\),临时leader树最多为\(\frac{n}{2^k+1}\),启动的msg数目最多为\(4*2^k\)

    消息复杂度:\(O(nlg \ n)\)

    1.3.2 同步环

    消息复杂度上界\(O(n)\),下界\(O(nlg \ n)\)

    上界\(O(n)\)

    • 非均匀:要求环中所有节点开始于同一轮
    • 均匀:节点可以开始于不同轮

    证明上界的非均匀算法

    必须知道环大小n,所有节点开始于同一轮

    假定id最小的为leader

    基本思想:按阶段运行,每个阶段由n轮组成。阶段\(i\)中,处理器id也为\(i\)的选举为leader,然后终止算法。

    各节点互不知道彼此的id值。

    消息复杂度:恰有n个消息被发送,\(O(n)\)

    证明上界的均匀算法

    无需知道环大小

    一个处理可以:自发唤醒或被动唤醒

    基本思想

    1. 源于\(id=i\)节点的msg,在被转发前延迟\(2^i-1\)轮。
    2. 每个自发唤醒的节点绕环发送一个唤醒msg,且无延迟
    3. 若节点在启动前收到唤醒msg,则该节点只作转发操作。

    只有自发唤醒的节点,才有可能选为leader

    初值:asleep=true;waiting = ф;R = 计算事件中接收msg的集合;s = ф;//the msg to be sent
    
    if asleep then {
        asleep:=false;
        if R = Φ then { // pi未收到过msg,属于自发唤醒
            min:=id;   // 参与选举
            s:=s+{<id>}; // 准备发送
        }else{ //已收到过msg,但此前未启动,被唤醒故Pi不参与
        	min:=∞; //选举,置min为∞ ,使其变为relay结点
        	// relay:=true; ?
        }
    }
    for each <m> in R do {// 处理完收到的m后相当于从R中删去
        if m < min then { // 收到的id较小时通过
        	become not elected;  // Pi未被选中
        	// 可用relay控制使转发节点不延迟?
        	将<m>加入waiting且记住m何时加入; // m加入延迟转发
        	min:=m;
        } // if m > min then it is swallowed
        if m=id then become elected; // Pi被选中
    } //endfor
    for each <m> in waiting do
        if <m> 是在2^m-1轮之前接收的 then
        	将<m>从waiting中删去并加入S
    send S to left;
    

    发送的消息:

    • 第一类:第一阶段的msg(唤醒msg
    • 第二类:最终leader的msg进入自己的第二阶段之前发送的第二阶段msg(其他节点发的)
    • 第三类:最终leader的msg进入自己的第二阶段之后发送的第二阶段msg(包括leader发的)

    第一类总数最多\(n\)

    第二类总数最多\(n\)

    第三类总数最多\(2n\)

    消息复杂度:\(O(4n)\)

    有限制的下界\(O(nlg \ n)\)

    序等价:两个环\(x_0,x_1,\cdots,x_n-1\)\(y_0,y_1,\cdots,y_n-1\)\(x_i < x_j,当且仅当y_i<y_j\)

    若一算法只与环上标识符之间的相对次序相关,而与具体id无关,则该算法一定只是基于标识符的比较

    对于每个\(n\ge8,n是2的方幂\),存在大小为n的环\(S_n\),使得基于比较的同步leader选举算法A,在容许执行里发送的msg数目为\(O(nlg \ n)\)

    构造\(S_n\)

    1. 定义大小为n的环\(R_n^{rev}\),令\(P_i\)的id为\(rev(i):i的二进制逆序列\)
    2. 将环划分为长度为\(j,j为2的方幂\)的连续片段,则这些片段是序等价的。
    3. 片断数为\(\frac{n}{j}\)

    1.4 计算模型

    计算模型的复杂性:

    • 系统由并发部件构成
    • 无全局时钟
    • 必须捕捉部件可能的失效

    对策:

    • 因果关系
    • 一致状态
    • 全局状态

    为什么分布式系统缺乏全局系统状态

    1. 非即时通信(传播延时,资源竞争,丢失msg重发)

    2. 相对性影响(大多数计算机的实际时钟存在漂移,时钟同步依旧是一个问题

    3. 中断(不可能在同一时刻观察一个分布式系统的全局状态)

    次序\(e_1 < e_2:事件e_1发生在e_2之前\)

    定序

    • 发生在同一节点上的事件满足全序,\(e_1<_pe_2\)
    • \(e_1\)发送消息,\(e_2\)接收消息,则\(e_1<_me_2\)

    Happens-before关系\(<_H\),一种偏序关系

    并发事件:两个事件不能由 \(<_H\) 定序

    有时将Happens-before关系描述为一个有向无环图

    image-20220103152117876

    如何将H关系的偏序关系转变成全序关系:

    • 在有向无环图DAG上的拓扑排序
    • Lamport算法

    1.4.1 Lamport时间戳

    基本思想

    • 事件e有附加时间戳:e.TS
    • 节点有局部时间戳:my_TS
    • msg有附加时间戳:m.TS
    • 节点执行事件时,将自己的时间戳赋给该事件。
    • 节点发送msg时,将自己的时间戳给所有的msg。
    • 接收消息时,本地时间戳更新为最大值
    • 发送消息时,使用本地时间戳打标签
    Initially: my_TS = 0;
    On event e:
        if(e == 接收消息m) then
        	my_TS = max(m.TS, my_TS)); // 取msg时间戳和节点时间戳较大值
         my_TS++;
         e.TS = my_TS; // 给事件e打时间戳
         if(e == 发送消息m) then
         	m.TS = my_TS; // 给消息打时间戳
    

    每一时间的时间戳大于前驱时间的时间戳

    问题:不同的时间可能有相同的时间戳(并发事件)

    改进算法:使用节点地址作为时间戳低位,如\(1.1,2.2\)。标号后按字典序得到全序关系。

    问题:无法通过时间戳判定两个事件是否有因果关系

    1.4.2 向量时间戳

    向量时间戳VT\(e.VT是个数组,e.VT[i]=k表示再节点i上,事件e之前有k个事件(可包括自己)\)

    基本思想

    • 节点有局部向量时间戳:my_VT

    • 事件e有向量时间戳:e.VT

    • msg有向量时间戳:m.VT

    Initially: my_VT=[0,0,,,0];
    On event e:
        if(e == 接收消息m) then
    		for i= 1 to M do // 向量时间戳的每个分量只增不减
        		my_VT[i] = max(m.VT[i], my_VT[i]);
        my_VT[self]++; // self是本节点的名字
        e.VT = my_VT; // 给事件e打时间戳
        if(e == 发送消息m) then
        	m.VT = my_VT; // 给消息m打时间戳
    

    向量时间戳比较:

    e1.VT = (5,4,1,3)
    e2.VT = (3,6,4,2)
    e3.VT = (0,0,1,3)
    
    1. e1和e2之间没有完全大于或完全小于的关系,则e1和e2是并发的。

    2. e3在因果序上先于e1

    1.4.3 因果通信

    处理器不能选择msg到达的时间,但是可以抑制过早到达的msg。

    如TCP中的FIFO通信。

    基本思想

    • 抑制从P发送的消息,知道可以断定没有其他消息早于m发生
    • 在每个节点上:
      • \(earliest[1...M]:不同节点当前能够传递的消息时间戳的下界\)
      • \(blocked[1...M]P:阻塞队列数组,每个分量是一个队列\)
    Causal Msg Delivery
    Definition:
        时间戳lk:
        	使用Lamport时间戳,lk=1;
         	使用向量时间戳,lk=(0,,,0,1,0,,,0),第k位为1;
    Initially:
        earliest[k] = lk,k=1,,,M // 不同节点当前能传递的消息时间戳的下界
        blocked[k] = {},k=1,,,M // 阻塞队列置空
            
    On the receipt of msg <m> from node P:
        delivery_list = {}
        if (blocked[p]==空) then
        	earliest[p] = m.timestamp;
         	blocked[p].push_back(m); // 处理收到的消息
        //处理阻塞队列
        while(∃k使blocked[k]非空 && 
        	对i=1,,,M(除k和self外) not_earliest(earliest[i],earliest[k],i) )
         	// 没有消息比k更早到
        {
        	将blocked[k]队头元素m’出队,且加入到delivery_list;
        	if (blocked[k]!=空) then
        		earliest[k] = m’.timestamp;
        	else
         		increment earliest[k] by lk
        }
        deliver the msgs in delivery_list; // 按因果序
    

    可能发生死锁(一节点上时间不发送你要的msg)

    该因果通信算法常用于组播

    本文来自博客园,作者:小陆斑比,转载请注明原文链接:https://www.cnblogs.com/bamlubi/p/15763704.html

  • 相关阅读:
    华东交通大学2017年ACM双基程序设计大赛题解
    hdu2010(dfs+剪枝)
    欧拉函数phic以及超大数的快速幂
    想了一天的题目QAQ 毛线数列的最值
    记一下STL的一个题
    hdu1877进制转换
    hdu1002大数相加
    hdu1576逆元的一道水题
    Courses
    CodeForce-813B The Golden Age(数学+枚举)
  • 原文地址:https://www.cnblogs.com/bamlubi/p/15763704.html
Copyright © 2011-2022 走看看