首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >二郎分布式算法仿真

二郎分布式算法仿真
EN

Stack Overflow用户
提问于 2015-02-11 13:57:26
回答 1查看 444关注 0票数 0

我是二郎的初学者。我想用它来观察“教科书”分发算法(领导人选举,协商一致.)的执行情况,以达到教学目的。在这个阶段,我将我的系统拓扑描述为一个图(从int到int列表),并在此基础上实例化和初始化节点的邻居列表。它工作得很好,但似乎有点特别。必须有一种更通用的方法来做到这一点。公共库或工具可以帮助吗?

如果没有,你觉得我做的事有道理吗?见下文。

代码语言:javascript
复制
-module(control).
-export([init/1, init/4]).

% create N processes 1 .. N and return a dict from
% 1..N to Pids
create(_, 0, Dict) -> Dict ;
create(Module, N, Dict) ->
  Id = spawn(Module, proc, [nil]),
  Id ! init_state,
  create(Module, N-1, dict:append(N, Id, Dict)).

% broadcast a Signal to all processes in Dict
broadcast(Dict, Signal) ->
  F = fun (_, [Y]) -> Y ! Signal end,
  dict : map (F, Dict),
  ok. 

% send a Signal to process Dict(I)
send(Dict, I, Signal) ->
  [Id] = dict : fetch(I, Dict),
  Id ! Signal,
  ok.

% wait for N ok signals
syncr(0) -> ok;
syncr(N) ->
  receive 
    ok -> io : format("ok received ~n", []), syncr(N-1) 
  end.

% init neighbors according to topology Graph
init_topology(Dict, Graph) ->
  F = fun(X) -> [Res] = dict : fetch(X, Dict), Res end,
  IdToPId = fun(L) -> lists : map(F, L) end,
  G = fun (I, [Y]) -> 
      [LId] = dict : fetch(I, Graph),
      LPId = IdToPId(LId),
      Y ! {neighbors, LPId, self()} end,
  dict : map (G, Dict),
  ok. 

% init all states with unary function Signal : I -> term.
init_state(Dict, Signal) ->
  F = fun (I, [Y]) -> Y ! {init, Signal(I), self()} end,
  dict : map (F, Dict),
  ok. 

% init all process according to the given topology and Signal : I -> term
% returns a pair of function Send and Broadcast
init(Module, N, Graph, Signal) ->
  Dict = create(Module, N, dict:new()),
  init_topology(Dict, Graph),
  init_state(Dict, Signal),
  syncr(2 * N),
  Send = fun (I, S) -> send(Dict, I, S) end,
  Broadcast = fun (S) -> broadcast(Dict, S) end,
  { Send, Broadcast }.

% this is a particular instanciation of a consensus algorithm with 
% N nodes
% a complete graph topology
% some initialisation of the process states
% the S and B returned functions allows me to interact with the system
% to start the algorithm for instance
init(N) -> {S, B} = control : init(consensus, N, topology : complete(N), fun(_)
      -> random : uniform(1000) end), {S,B}.
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-02-11 22:11:11

OTP有一些死记硬背的方法来处理上面的任务。我说的是“死记硬背”而不是“泛型”,因为它们是OTP约定,不是通用分布式算法实现的普遍接受的解决方案。

诸如初始化进程图、消息传递、终止、同步信令等都是OTP在application/supervisor/gen_*概念中提供解决方案的类型。维护进程注册表可以由global模块、实用程序(如gproc )或使用流程组来处理--但您处理流程组的方式似乎更适合于进程注册中心,甚至是当前的流程字典(分配给给定进程的整数标签没有意义,不太可能需要向特定进程N发送消息,而不需要它启动消息链本身,在这种情况下,您可以知道它的PID)。

在任何情况下,当您试图解决实际的现实世界问题时,启动进程图的OTP方法是最有用的,而不是理论问题。在理论系统中,没有什么是失败的,代码是完美的,并且没有用户--你正在建模一个理想的情况。在现实世界中,事情会中断,需要被监控,臭虫很多,人们会被电线和网络电缆绊倒,而日常生活中常见的情况通常是一团糟。现实世界中的混乱正是OTP设计来帮助解决的问题,它只是以一种死记硬背的方式将程序声明为一个进程图--这是偶然的事实,这是为什么“参与者模型”和分布式计算理论的语言在Erlang/OTP文档中使用不多的原因之一。

以OTP方式启动系统的一个副作用是监视、监视和其他一些实际有用的东西(如“在用户依赖于系统可用的生产环境中有用”),application给您提供的东西“只是发生”,而不需要添加一堆用于监视、调试或临时监控策略的代码。但这些可能不是你真正关心的事情。

OTP没有提供的是一组通用的协商一致算法实现。在大多数实际系统中(再一次,这是Erlang的真正重点),决定将协商一致的复杂性降到最低,并依靠任意条件强制遵守领导模式,即使这是暂时具有破坏性的。

因此,一方面“是”,Erlang/OTP提供死记硬背的方法来处理上面所写的大部分代码,但另一方面,Erlang/OTP的设计并没有考虑到任何特定的分布式计算理论模型,因此它的编程文化和框架已经有意识地决定将更高的优先级放在一些特性上,这些特性为在生产中部署健壮的系统提供了捷径,而在实现或坚持理论基础上则优先级较低,因此您可能会忽略一些功能。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28456186

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档