一切为了并行:MS Axum语言教程

上传人:e****s 文档编号:26012631 上传时间:2017-12-21 格式:DOCX 页数:8 大小:51.32KB
返回 下载 相关 举报
一切为了并行:MS Axum语言教程_第1页
第1页 / 共8页
一切为了并行:MS Axum语言教程_第2页
第2页 / 共8页
一切为了并行:MS Axum语言教程_第3页
第3页 / 共8页
一切为了并行:MS Axum语言教程_第4页
第4页 / 共8页
一切为了并行:MS Axum语言教程_第5页
第5页 / 共8页
点击查看更多>>
资源描述

《一切为了并行:MS Axum语言教程》由会员分享,可在线阅读,更多相关《一切为了并行:MS Axum语言教程(8页珍藏版)》请在金锄头文库上搜索。

1、Axum 一个刚刚问世.net 家族的新丁,几乎是和这篇文章一样新。它的诞生只为一个目的:一切为了并行。 编写并行程序并不容易,首先要将方案切割为许多并行任务(Task)。较为简单的方案,如计算每只股票的年收益率,很容易实施并行,因为任务之间彼此独立。但另外一些方案则十分复杂,任务之间彼此依赖且要相互协作,比如网络游戏。 Axum 试图提供一种更为自然的方式来安排组件之间的协作问题。换句话说,如果将方案按照交互式组件建模,在Axum 中编码会更为直接了当,而且你可能可以不被许多常见的并发问题所困扰。 并行的另一个目的是为了提速。经常,程序的反应速度总被象 I/O 或者用户输入这样的慢速组件所拖

2、累。比如email 客户端通过慢速的网络下载邮件的时候,程序还应该能继续响应用户的动作。 Axum 的目标之一就是程序不需要再担心并发问题,理论上,你的程序将变得快速而且响应及时。为此,Axum 不允许自由的共享和变更线程的状态,而只允许“有节制地”存取共享的状态,这解决了许多并发问题。 从Hello,World开始 Axum 的安装包提供了 Visual Studio 的集成,你可以在 Visual Studio 2008 中使用 Axum 的解决方案。 我们从最简单的Hello,World入手。 Java 代码 1. using System; 2. agent Program : Mic

3、rosoft.Axum.ConsoleApplication 3. override int Run(String args) 4. Console.WriteLine(Hello, World!.MS Axum By Ray_Linn!); 5. 6. 这段程序以关键字“agent”开始,Axum 中“代理”的概念来自模式中常见的“参与者模式”:参与者被描述成自治的实体,互相之间则通过消息来沟通,处理它们从其他参与者接受的数据,并发送给其他参与者。Axum 中参与者表现为“代理”. 用 Axum 编写程序都是在定义代理并安排他们之间的交互。在许多方面,基于代理编程都不同于面向对象编程。首先不

4、同于对象,代理不提供公共方法或展示他们的状态。你不能“进入”代理修改任何字段。你不能调用代理的方法并等它给你结果。相反地,你可以给它发送消息,要求它完成之后给你个响应。 Axum 提供了一些支持类库包括ConsoleApplication等代理,这个代理完成了控制台程序”所需的一些工作:启动,设置命令行参数,停止。 上面的程序中的代理衍生自 ConsoleApplication,因此我们重写(Override)入口点的 Run 方法。因为 Axum 是.net家族中的一员,它可以分享已有的所有类库。比如程序中的 System.Console.WriteLine 就来自基础类库 BCL. 消息流

5、动 -Message-Passing “消息流动”这个词是我杜撰的,因为它很形象地说明了 Axum 中的类似流水的消息处理方式,这里我们要介绍两个概念 channel-通道和通道的端口 port。 代理就像是个水处理机一样,它是提供数据处理的组件,它也有进水口和出水口-我们称之为通道(channel),不同的数据则从不同的通道端口(channel port)流经代理。先看个简单的例子 Java 代码 1. using System; 2. agent Program : channel Microsoft.Axum.Application 3. public Program() 4. / Re

6、ceive command line arguments from port CommandLine String 5. args = receive(PrimaryChannel:CommandLine); 6. / Send a message to port ExitCode: 7. PrimaryChannel:ExitCode (); 18. / Create pipeline: 19. numbers = Fibonacci = ProcessResult; 20. / Send messages to numbers: 21. for( int i=0; i的实例,它是一个同时扮

7、演“源头”与“目标”的交互点。“ordered”意味着消息接受和发送的顺序是一致的。 接下来,代理创建了用消息传递操作符 “=”构造了数据流网。 Java 代码 1. numbers = Fibonacci = PrintResult; 这个表达式应该被理解为“当一个消息到达交互点“number”时,将它传递到由“Fibonacci”实现的转换交互点,最后传递结果到 PrintResult 方法”。 将消息从一个节点传递至另一个节点的数据流网相当普遍的,它有一个名称“管道”。 由于 Fibonacci 函数没有副作用,Axum 运行时会产生能让程序最高效运行所需的线程,以便并发执行转换工作。

8、函数经常被用在管道和其他类型网络中的并发执行节点上。代理编程 上面的斐波那契数列的例子只是展示了一个微不足道的构建数据流网的例子。这类网络适合那些“数据流入,数据流出”的场景,但它不能指定数据如何在网络中传播,也不允许不同类型的数据流入或者流出网络。 代理与通道给了我们创建复杂数据流网所需的一切。 通过通道沟通的两个代理是种弱关系:它不需要知道或关系另一个代理是如何实现的。它们之间的“契约”只由通道指定。借用 OOP 中的概念,通道扮演了接口的角色,而代理则是实现了该接口的类。 使用通道时,你向输入端口发送数据,从输出端口接受数据,这里,输入端口扮演了目标,而输出端口扮演了源头。而实现通道时,

9、输入端口则是源头,输出端口则是目标。这有点难以理解,想想家里的水处理机,如果水是数据的话,考虑水的流向,你把水倒入入水口(水相对于你是流出),从出水口接水(水相对于你是流入),而处理机内部而言,水则是从进水口流入,从出水口流出。 请看例子,有个“Adder”通道接受输入两个数字并得出二者之和。通道的使用者发送数字到输入端口 Num1 和Num2,并从输出端口 Sum 接收结果。MainAgent 代理是通道的使用者,而 AdderAgent 实现了该通道。 Java 代码 1. channel Adder 2. input int Num1; 3. input int Num2; 4. out

10、put int Sum; 5. 6. 7. agent AdderAgent : channel Adder 8. 9. public AdderAgent() 10. 11. int result = receive(PrimaryChannel:Num1) + receive(PrimaryChannel:Num2); 12. PrimaryChannel:Sum (c); 如果编译时,编译器知道这种强制转换会失败的话,Axum 编译器将报错,反之,编译器将产生代码,但这些代码可能在运行时报错的。schema 还可以将许多不同的数据类型包装成一个单一的包装类型以便在一个消息中一次发送。 请

11、求/回答端口 回顾上面的例子,它只能接受一次请求,之后代理 AdderAgent 就关闭了。我们可以修改 AdderAgent 让它继续接受新的起请求直到满足某些条件才关闭。这是个好的开始,不过如果我们希望用户能够提交多个请求,并按发送顺序接受这些请求,这该怎么办?为此,我们需要某种方法来关键请求与 AdderAgent 产生的结果。一个方法是返回个收据给客户端,客户端稍后凭此来认领结果。在 Axum 种,这种收据被称为请求关联(request correlator),支持请求关联的端口则成为请求/回答端口(request-reply ports).我们接下来修改上面的例子 Java 代码 1

12、. using System; 2. using System.Concurrency; 3. using Microsoft.Axum; 4. 5. schema Pair 6. required int Num1; 7. required int Num2; 8. 9. 10.channel Adder 11. 12. input Pair Nums : int; / input request-reply port 13. 14. 15.agent AdderAgent : channel Adder 16. 17. public AdderAgent() 18. while(true)

13、 19. var result = receive(PrimaryChannel:Nums); 20. result GotNum1; 6. GotNum1: Num2 - GotNum2; 7. GotNum2: Sum - End; 8. 开始协议带有状态“Start”,当端口 Num1 收到一条消息时,状态变换成 GotNum1,如果其他端口在这时得到消息将导致违反协议异常。接下来,状态变成 GotNum1,下个被使用的端口应该是 Num1,它将触发状态变迁成GotNum2.最后端口 Sum 上的消息将触发变迁成内建的状态End。这时,协议被关闭了,任何再试图向端口发送消息将触发异常。

14、你可以定义更详细描述的变迁来使协议更丰富,比如可以“当消息到达端口 X 或 Y,变迁到状态 Y”或者“当消息的值大于 10 的时候,变迁到状态 X等等。为简单起见,我们不做详述,你可参考 Axum 的规格书。 我们试着改变上上个例子,用上面带协议的通道并注释掉这行 Java 代码 1. adder:Num1 (my adder); 当用户请求保有在my adder地址的Adder服务时,代理 AdderAgent 将被实例化,关联到当前域,并返回通道Adder 的 using end。保有代理类型的地址可以是任何表达式,只要支持“等于”比较。这儿我们选择字符,因为它是描述性的。 因为 Host

15、 方法将代理与当前域相关联(它是个域方法),它只能在域的上下文中被执行,而不能在域之外声明的 agent 中。 现在,代理可以这样被实例化: Java 代码 1. var adder = new Adder(my adder); 这可以理解为“创建通道 channel 的 using end,该通道由保有在地址“my adder的服务所实现”。 注意:用户不了解这个代理的类型,他所要关心的只是通道的类型和实现该通道的服务的地址。 为了更好理解代理作为服务的想法,想一下一个给个数字会返回相应的斐波那契数列的通道。不象加法,只有一种有意义的方式,斐波那契额数列可以用很多种不同的计算方法,高效的低效的。 同一个 Fibonacci 通道可以由两个不同的代理来实现,让我们称他们为 FibonacciSlow 和 FibonacciFast,这两个代理类型被保有在不同的地址上: Java 代码 1. Host(slow); 2. Host(fast);

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 行业资料 > 其它行业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号