14.1.1 命令式代码的并行化

在命令式编程中,for 循环可能是很容易并行化的最常见结构。循环的迭代器独立(independent)时,就可以在单独的线程上执行。就是说,由于独立,迭代器不会依赖前面任何迭代器所计算的值。

例如,统计数组中元素时,要计算下一个元素,就需要统计前面元素的总和。(这仍可以并行,但是不那么简单。)回想一下我们在第十章实现的“模糊”数组的函数,非常适合并行化:虽然每次迭代使用输入数组的多个元素,但它不依赖输出数组中的任何元素。清单 14.1 显示了基于前面示例的简单 for 循环,包含 C# 和 F# 两个版本。

清单14.1 用 for 循环计算模糊数组 (C# and F#)

C#  F#
for(int i=1; i<inp.Length-1; i++){
  var sum = inp[i-1] +
    inp[i] + inp[i+1];
  res[i] = sum / 3;
}   for i in 1 .. inp.Length - 2 do
  let sum = inp.[i-1] +
             inp.[i] + inp.[i+1]
  res.[i] <- sum / 3

虽然这是命令式代码,但仍可以成为纯函数式程序的一部分。Inp 是输入数组,在代码中的所有地方都不能修改,res 是输出数组,在循环计算后,也不应该进行修改。

要将循环并行化,可以使用 Parallel.For 方法。这个类在命名空间 System.Threading.Tasks 下,只在 .NET 4.0 上才可用。Parallel.For 方法的参数为 Action 委托值,可以由 lambda 函数提供。F# 中,直接使用这个方法感觉有点大材小用,所以,我们会定义一个简单的函数,使代码更简洁:

let pfor nfrom nto f =
  Parallel.For(nfrom, nto + 1, Action<_>(f)) |> ignore

这段代码把函数 f (其类型为 int -> unit)包装在委托类型,运行并行的 for 循环。方法返回循环是否成功完成的信息,但我们并不需要,所以就忽略了。注意,我们还在上限上加了 1,因为在 F# 的 for 循环是包容上限的,而在 C# for 循环和 Parallel.For 方法中是不包含上限的。清单 14.2 显示前面示例的并行化版本。

清单14.2 并行折 for 循环 (C# and F#)

C# F#

Parallel.For(1,inp.Length-1,i => {
  var sum = inp[i-1] +
    inp[i] + inp[i+1];
  res[i] = sum / 3;
}); pfor 1 (inp.Length-2) (fun i –>
  let sum = inp.[i-1] +
            inp.[i] + inp.[i+1]
  res.[i] <- sum / 3
)

可以发现,这与原始的串行版本几乎一样简单。另外,还表明了函数式构造的强大:由于有 lambda 函数,把串行的 for 循环转换为并行时,唯一要做的是使用 Parallel.For 方法(或在 F# 中使用 pfor 函数),代替内置的语言构造。

注意

在 Parallel 类中,除了有 For 方法,还有 ForEach 方法,可用于对 C# 中的 foreach 构造,或 F# 中的 for …in … do 构造进行并行化。这两个方法都可以重载,自定义迭代器。重载可以改变步长,增加 For 方法中的索引,或者停止并行执行(类似于 C# 中的循环中断break)。如果觉得需要更多一点儿控制,就请参考文档,看看其中是否有重载可以帮助你。

处理数组和其他命令式数据结构,Parallel.For 方法特别有用。在这一章的后面(第 14.2.5 节),我们会在更大的示例应用程序中再次用它来以函数方式处理数组。现在,就先结束介绍,下面要讨论的两种技术都是纯函数式的。

时间: 2024-10-03 13:39:05

14.1.1 命令式代码的并行化的相关文章

14条最佳JS代码编写技巧

http://gaohaixian.blog.163.com/blog/static/123260105201142645458315/写任何编程代码,不同的开发者都会有不同的见解.但参考一下总是好的,下面是来自Javascript Toolbox发布的14条最佳JS代码编写技巧,Sofish翻译(1,2). 1. 总是使用 ‘var’ 在javascript中,变量不是全局范围的就是函数范围的,使用”var”关键词将是保持变量简洁明了的关键.当声明一个或者是全局或者是函数级(function-

14款优秀的代码展示网站

本文列出的这些网站可以分享和展示你的代码.它们都提供在线预览功能,所以别人可以看到你的代码如何运行.它们有时候也被称作“代码广场”或者“沙箱”. 它们不仅仅提供简单的代码展示功能,还提供很多代码协作和实际编程过程会用到的功能.例如,当你需要别人帮你调试源代码的时候,可以使用这些网站分享你有问题的代码,然后把链接分享给帮助你的人.这使得他们可以方便的查看你的源代码并提供解决方案. 1.CodePen 在CodePen上,你可以演示被称作 pens 的代码.Pen 由 HTML.CSS和JS组成.C

《Code Complete》ch.14 组织直线型的代码

WHAT? 最简单的控制流:即按照先后顺序放置语句与语句块 WHY? 尽管组织直线型的代码是一个简单的任务,但代码结构上的一些微妙之处还是会对代码质量.正确性.可读性和可维护性带来影响 HOW? 必须有明确顺序的语句 使依赖关系变得非常明显 使子程序名能突显依赖关系 利用子程序参数表明依赖关系 用注释说明 用断言/错误处理代码来检查依赖关系 顺序无关的语句 使代码易于自上而下的阅读,将相关的代码组织到一起 // bad MarketingData marketingData; SalesData

[Spring cloud 一步步实现广告系统] 14. 全量索引代码实现

上一节我们实现了索引基本操作的类以及索引缓存工具类,本小节我们开始实现加载全量索引数据,在加载全量索引数据之前,我们需要先将数据库中的表数据导出到一份文件中.Let's code. 1.首先定义一个常量类,用来存储导出文件存储的目录和文件名称 因为我们导出的文件需要在搜索服务中使用到,因此,我们将文件名 & 目录以及导出对象的信息编写在mscx-ad-commom项目中. public class FileConstant { public static final String DATA_RO

ubuntu 14.04 vim YoucompleteMe 代码自动补全工具安装

安装步骤如下: sudo apt-get install vim ; sudo apt-get install vim-youcompleteme ; sudo apt-get install vim-addon-manager ; vam install youcompleteme .

14.1 理解不同的并行技术

在这一节,我们将讨论三种技术,并使用简单的示例进行演示.我们将使用的 .NET并行扩展(Parallel Extensions to .NET),是并行编程库,它是 .NET Framework 4.0 标准的一部分,但是,不幸的是,在早期 .NET 的版本中没有.如果要在 Visual Studio 2008 中体验并行扩展,可以下载 CTP 版本,但有几个命名上的改变(实际上,Visual Studio 2010 应该没有这个问题了). .NET 的并行扩展(Parallel Extensi

[Java 8] (10) 使用Lambda完成函数组合,Map-Reduce以及并行化

Java 8中同时存在面向对象编程(OOP)和函数式编程(FP, Functional Programming)这两种编程范式.实际上,这两种范式并不矛盾,只是着重点不同.在OOP中,着重于通过丰富的类型系统对需要解决的问题进行建模:而FP中则着重于通过高阶函数和Lambda表达式来完成计算.所以我们完全可以将这两者融合在一起,对问题提出更加优雅的解决方案. 在这篇文章中,会介绍如何通过函数组合(Function Composition)来将若干个函数单元组合成一个Map-Reduce模式的应用

命令式编程vs声明式编程

英文原文:Imperative vs Declarative 先统一一下概念,我们有两种编程方式:命令式和声明式. 我们可以像下面这样定义它们之间的不同: 命令式编程:命令"机器"如何去做事情(how),这样不管你想要的是什么(what),它都会按照你的命令实现. 声明式编程:告诉"机器"你想要的是什么(what),让机器想出如何去做(how). 声明式编程和命令式编程的代码例子举个简单的例子,假设我们想让一个数组里的数值翻倍. 1.我们用命令式编程风格实现,像下面

声明式编程与命令式编程

先统一一下概念,我们有两种编程方式:命令式和声明式. 我们可以像下面这样定义它们之间的不同: ·命令式编程:命令“机器”如何去做事情(how),这样不管你想要的是什么(what),它都会按照你的命令实现.·声明式编程:告诉“机器”你想要的是什么(what),让机器想出如何去做(how). 声明式编程和命令式编程的代码例子: 举个简单的例子,假设我们想让一个数组里的数值翻倍. 我们用命令式编程风格实现,像下面这样: var numbers = [1,2,3,4,5] var doubled = [