Scala 具体的并行集合库【翻译】
本文内容
- 并行数组(Parallel Array)
- 并行向量(Parallel Vector)
- 并行范围(Parallel Range)
- 并行哈希表(Parallel Hash Tables)
- 并行散列 Tries(Parallel Hash Tries)
- 并行并发 Tries(Parallel Concurrent Tries)
- 参考资料
并行数组(Parallel Array)
一个 ParArray 序列包含线性、连续的元素数组。这意味着,通过修改底层数组,可以高效地访问和修改元素。因此,反序元素也很高效。并行数组跟数组一样也是固定大小的。
scala> val pa = scala.collection.parallel.mutable.ParArray.tabulate(1000)(x =>2*
x +1)
pa: scala.collection.parallel.mutable.ParArray[Int] = ParArray(1, 3, 5, 7, 9, 11
, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51
, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91
, 93, 95, 97, 99, 101, 103, 105, 107, 109, 111, 113, 115, 117, 119, 121, 123, 12
5, 127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 151, 153, 155, 15
7, 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 18
9, 191, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 22
1, 223, 225, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 25
3, 255, 257, 259, 261, 263, 265, 267, 269, 271, 273, 275, 277, 279, 281, 283, 28
5, 287, 289, 291, 293, 295, 297, 299, 301, 303, 305, 307, 309, 311, 313, 315,...
scala> pa reduce(_+_)
res0: Int = 1000000
scala> pa map(x=>(x-1)/2)
res1: scala.collection.parallel.mutable.ParArray[Int] = ParArray(0, 1, 2, 3, 4,
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 2
6, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 4
6, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 6
6, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 8
6, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152,
153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 16...
scala>
并行向量(Parallel Vector)
一个 ParVector 是一个不可变序列,具有低常量因子对数的访问(low-constant factor logarithmic access )和更新时间。
scala> val pv = scala.collection.parallel.immutable.ParVector.tabulate(1000)(x =
> x)
pv: scala.collection.parallel.immutable.ParVector[Int] = ParVector(0, 1, 2, 3, 4
, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104
, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120
, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136
, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152
, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, ...
scala> pv filter (_ %2==0)
res2: scala.collection.parallel.immutable.ParVector[Int] = ParVector(0, 2, 4, 6,
8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46,
48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86,
88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 1
22, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 1
54, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 1
86, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 2
18, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 2
50, 252, 254, 256, 258, 260, 262, 264, 266, 268, 270, 272, 274, 276, 278, 280, 2
82, 284, 286, 288, 290, 292, 294, 296, 298, 300, 302, 304, 306, 308, 310, 312...
scala>
并行范围(Parallel Range)
一个 ParRange 是一个有序的等差整数数列(an ordered sequence of elements equally spaced apart)。并行范围(parallel range)的创建与顺序范围类似(sequential Range)。
scala> 1 to 3 par
warning: there were 1 feature warning(s); re-run with -feature for details
res3: scala.collection.parallel.immutable.ParRange = ParRange(1, 2, 3)
scala> 15 to 5 by -2 par
warning: there were 1 feature warning(s); re-run with -feature for details
res4: scala.collection.parallel.immutable.ParRange = ParRange(15, 13, 11, 9, 7,
5)
scala>
并行哈希表(Parallel Hash Tables)
并行哈希表(Parallel hash tables)存储底层数组的元素,并将它们放置在由各自元素哈希码的位置。并行可变哈希集(mutable.ParHashSet)和并行可变哈希映射(mutable.ParHashMap)都是基于哈希表。
scala> val phs = scala.collection.parallel.mutable.ParHashSet(1 until 2000: _*)
phs: scala.collection.parallel.mutable.ParHashSet[Int] = ParHashSet(307, 1705, 3
67, 1007, 1954, 1067, 1316, 1033, 707, 1980, 335, 1093, 395, 1342, 1016, 644, 12
65, 35, 704, 95, 1042, 344, 1291, 1044, 404, 1991, 1351, 653, 1353, 1602, 1662,
1379, 1053, 41, 1628, 1302, 1688, 1362, 1079, 381, 1328, 441, 1388, 690, 1637, 9
39, 1390, 1697, 52, 999, 18, 1699, 639, 78, 1665, 1339, 327, 1, 1725, 1399, 1648
, 1365, 27, 1708, 1425, 727, 1674, 976, 1734, 89, 1036, 1983, 676, 115, 736, 38,
985, 287, 1045, 1685, 347, 64, 1745, 313, 1711, 1385, 373, 1013, 1771, 1073, 13
22, 1382, 773, 75, 1022, 1969, 324, 1082, 384, 1657, 1331, 633, 350, 24, 693, 41
0, 84, 1357, 659, 333, 50, 1731, 719, 393, 110, 359, 1059, 419, 361, 668, 1119,
421, 1368, 728, 670, 1617, 730, 1677, 1394, 979, 696, 370, 1643, 1317, 756, 4...
scala> phs map (x => x * x)
res5: scala.collection.parallel.mutable.ParHashSet[Int] = ParHashSet(11236, 2563
201, 1957201, 143641, 227529, 3556996, 1214404, 1946025, 670761, 2181529, 219024
, 1648656, 2062096, 2152089, 343396, 2418025, 1582564, 440896, 925444, 312481, 3
526884, 2775556, 3359889, 175561, 35721, 84681, 2244004, 20164, 2102500, 576081,
1557504, 338724, 952576, 300304, 1030225, 3139984, 687241, 1227664, 2627641, 35
75881, 51984, 851929, 94249, 2505889, 3972049, 788544, 1459264, 2937796, 2920681
, 2446096, 413449, 59536, 690561, 306916, 441, 2647129, 5929, 1054729, 746496, 3
392964, 3207681, 2989441, 2547216, 180625, 1868689, 166464, 33124, 237169, 25856
64, 1, 3625216, 57600, 99225, 315844, 251001, 238144, 32761, 595984, 1194649, 12
18816, 676, 1464100, 797449, 2131600, 1527696, 2383936, 786769, 3697929, 3222...
scala>
并行散列 Tries(Parallel Hash Tries)
并行哈希 tries(Parallel hash tries )是不可变哈希 tries(immutable hash tries)的并行版本,它用来高效地表示不可变集(immutable sets)和映射(immutable maps)。他们由 immutable.ParHashSet 和 immutable.ParHashMap 支持。
scala> val phs = scala.collection.parallel.immutable.ParHashSet(1 until 1000: _
)
phs: scala.collection.parallel.immutable.ParHashSet[Int] = ParSet(645, 892, 69,
809, 629, 365, 138, 760, 101, 479, 347, 846, 909, 333, 628, 249, 893, 518, 962,
468, 234, 941, 777, 555, 666, 88, 481, 352, 408, 977, 170, 523, 582, 762, 115,
83, 730, 217, 276, 994, 308, 741, 5, 873, 449, 120, 247, 379, 878, 440, 655, 51
, 614, 269, 677, 202, 597, 861, 10, 385, 384, 56, 533, 550, 142, 500, 797, 715,
472, 814, 698, 747, 913, 945, 340, 538, 153, 930, 670, 829, 174, 404, 898, 185,
42, 782, 709, 841, 417, 24, 973, 885, 288, 301, 320, 565, 436, 37, 25, 651, 257
389, 52, 724, 14, 570, 184, 719, 785, 372, 504, 110, 587, 619, 838, 917, 702,
51, 802, 125, 344, 934, 357, 196, 949, 542, 460, 157, 817, 902, 559, 638, 853,
89, 20, 421, 870, 46, 969, 93, 606, 284, 770, 881, 416, 325, 152, 228, 289, 4..
scala> phs map { x => x * x } sum
warning: there were 1 feature warning(s); re-run with -feature for details
res6: Int = 332833500
scala>
并行并发 tries(Parallel Concurrent Tries)
concurrent.TrieMap 是一个并发线程安全的映射(map),而mutable.ParTrieMap 是它的并行版本。若果数据结构在遍历期间被修改,那么大多数并发数据结构不能保证一致性,Ctries 保证在下一次迭代中更新是可见的。这意味着,当你遍历是,可以改变并发 trie,如下例子所示,输出1到99的平方根。
scala> val numbers = scala.collection.parallel.mutable.ParTrieMap((1 until 100)
zip (1 until 100): _*) map {case(k, v)=>(k.toDouble, v.toDouble)}
numbers: scala.collection.parallel.mutable.ParTrieMap[Double,Double] = ParTrieMa
p(15.0 -> 15.0, 51.0 -> 51.0, 33.0 -> 33.0, 48.0 -> 48.0, 84.0 -> 84.0, 30.0 ->
30.0, 66.0 -> 66.0, 12.0 -> 12.0, 27.0 -> 27.0, 9.0 -> 9.0, 99.0 -> 99.0, 81.0 -
> 81.0, 63.0 -> 63.0, 45.0 -> 45.0, 78.0 -> 78.0, 60.0 -> 60.0, 96.0 -> 96.0, 19
.0 -> 19.0, 1.0 -> 1.0, 37.0 -> 37.0, 52.0 -> 52.0, 88.0 -> 88.0, 34.0 -> 34.0,
70.0 -> 70.0, 16.0 -> 16.0, 67.0 -> 67.0, 13.0 -> 13.0, 49.0 -> 49.0, 85.0 -> 85
.0, 31.0 -> 31.0, 82.0 -> 82.0, 64.0 -> 64.0, 46.0 -> 46.0, 5.0 -> 5.0, 56.0 ->
56.0, 2.0 -> 2.0, 38.0 -> 38.0, 74.0 -> 74.0, 20.0 -> 20.0, 89.0 -> 89.0, 71.0 -
> 71.0, 17.0 -> 17.0, 53.0 -> 53.0, 35.0 -> 35.0, 86.0 -> 86.0, 68.0 -> 68.0, 32
.0 -> 32.0, 50.0 -> 50.0, 83.0 -> 83.0, 6.0 -> 6.0, 42.0 -> 42.0, 24.0 -> 24....
scala> while(numbers.nonEmpty){
| numbers foreach{case(num, sqrt)=>
| val nsqrt =0.5*(sqrt + num / sqrt)
| numbers(num)= nsqrt
| if(math.abs(nsqrt - sqrt)<0.01){
| println(num, nsqrt)
| numbers.remove(num)
| }
| }
| }
(1.0,1.0)
(2.0,1.4142156862745097)
(5.0,2.2360688956433634)
(6.0,2.4494943716069653)
(3.0,1.7320508100147274)
(7.0,2.64576704419029)
(4.0,2.0000000929222947)
(15.0,3.872983698008724)
(12.0,3.4641016533502986)
(9.0,3.000000001396984)
(19.0,4.358901750853372)
(16.0,4.000000636692939)
(13.0,3.6055513629176015)
(20.0,4.4721402170657)
……
scala>
性能特征
顺序类型(sequence types)的性能特点:
| head | tail | apply | update | prepend | append | insert | |
| ParArray | C | L | C | C | L | L | L |
| ParVector | eC | eC | eC | eC | eC | eC | - |
| ParRange | C | C | C | - | - | - | - |
集(set)和映射(map)类型的性能特点:
| lookup | add | remove | |
| immutable | |||
| ParHashSet/ParHashMap | eC | eC | eC |
| mutable | |||
| ParHashSet/ParHashMap | C | C | C |
| ParTieMap | eC | eC | eC |
键(Key)
上面两个表的条目,说明如下:
| C | 该操作花费常量时间(快) |
| eC | 该操作有效地花费常量时间,但可能依赖于某些假设,如向量的最大长度或哈希键的离散性 |
| aC | 该操作花费分期常量时间。Some invocations of the operation might take longer, but if many operations are performed on average only constant time per operation is taken. |
| Log | 该操作花费时间与集合大小的对数成比例 |
| L | 该操作是线性的,花费的时间与集合大小成比例 |
| - | 该操作不被支持 |
下表处理序列类型——可变和不可变——具备如下操作:
| head | 选择序列的第一个元素 |
| tail | 产生一个由除了第一个元素的所有元素组成的新序列 |
| apply | 索引 |
| update | 对于不可变序列(immutable sequence)的函数式更新,对于可变序列(mutable sequences)的副作用(side effect)更新 |
| prepend | 添加一个元素到序列前面。针对不可变序列,这将产生一个新序列。针对可变序列,这将修改已经存在的序列 |
| append | 添加一个元素到序列尾部。针对不可变的序列,这将产生一个新序列,针对可变序列,这将修改已经存在的序列。 |
| insert | 在序列中的任意位置插入一个元素。只支持可变序列(mutable sequence) |
下表处理可变和不可变集(set)和映射(map)具有如下操作:
| lookup | 测试一个元素是否包含在集(set)中,或选择与键有关的值 |
| add | 添加一个元素到集(set),或添加键/值对到映射(map) |
| remove | 从集(set)或删除一个元素,或从映射(map)删除一个键 |
| min | 集(set)中最小的元素,或映射(map)中最小的键 |
参考资料
Scala 具体的并行集合库【翻译】的更多相关文章
- Scala——的并行集合
当出现Kafka单个分区数据量很大,但每个分区的数据量很平均的情况时,我们往往采用下面两种方案增加并行度: l 增加Kafka分区数量 l 对拉取过来的数据执行repartition 但是针对这种 ...
- scala 数据结构(十一):流 Stream、视图 View、线程安全的集合、并行集合
1 流 Stream stream是一个集合.这个集合,可以用于存放无穷多个元素,但是这无穷个元素并不会一次性生产出来,而是需要用到多大的区间,就会动态的生产,末尾元素遵循lazy规则(即:要使用结果 ...
- (原创)发布一个c++11开发的轻量级的并行Task库TaskCpp
TaskCpp简介 TaskCpp是c++11开发的一个跨平台的并行task库,它的设计思路来源于微软的并行计算库ppl和intel的并行计算库tbb,关于ppl和tbb我在前面有介绍.既然已经有了这 ...
- Scala集合和Java集合对应转换关系
作者:Syn良子 出处:http://www.cnblogs.com/cssdongl 转载请注明出处 用Scala编码的时候,经常会遇到scala集合和Java集合互相转换的case,特意mark一 ...
- geotrellis使用(六)Scala并发(并行)编程
本文主要讲解Scala的并发(并行)编程,那么为什么题目概称geotrellis使用(六)呢,主要因为本系列讲解如何使用Geotrellis,具体前几篇博文已经介绍过了.我觉得干任何一件事情基础很重要 ...
- java11 Guava:谷歌开发的集合库
Guava:谷歌开发的集合库,通过build path->Add External JARs 把guava.jar包加进去. 版本控制工具:.CVS .SVN .git 所以需要下载git客户端 ...
- 并行模式库PPL应用实战(一):使用task类创建并行任务
自 VS2010 起,微软就在 CRT 中集成了并发运行时(Concurrency Runtime),并行模式库(PPL,Parallel Patterns Library)是其中的一个重要组成部分. ...
- C#编程(五十八)----------并行集合
并行集合 对于并行任务,与其相关紧密的就是对一些共享资源,数据结构的并行访问.经常要做的就是对一些队列进行加锁-解锁,然后执行类似插入,删除等等互斥操作. .NET4提供了一些封装好的支持并行操作数据 ...
- C#高级编程五十八天----并行集合
并行集合 对于并行任务,与其相关紧密的就是对一些共享资源,数据结构的并行訪问.常常要做的就是对一些队列进行加锁-解锁,然后运行类似插入,删除等等相互排斥操作. .NET4提供了一些封装好的支持并行操作 ...
随机推荐
- SQL基础分类
我们可以把学习过的sql语言,进行分类: 1. DDL : 数据定义语言 a) 操作库表结构的语言. Create drop alter 2. DML : 数据操作语言 a) 操作数据的语言: upd ...
- 10. Software, Software Engineering, water fall (瀑布模型),Code Complete等名词的来源
①.Software-软件”一词是20世纪60年代才出现的,软件Software——1958年由贝尔实验室的著名统计学家John Tukey 提出软件与硬件一起构成完整的计算机系统,它们是相互依存,缺 ...
- IPD模式下开展敏捷开发的一些问题汇总
1. 我们现在普遍用的是老系统情况下,什么时候把软件和硬件在敏捷项目里面集成? 答:有两种场景:第一种场景是把软件分几个迭代,最后把软件和硬件一起集成:第二种场景是更好的一种场景,每几个迭代 ...
- Install nutch
1. Install nutch on single node: $apt-get install subversion $apt-get install ant $svn co https://sv ...
- iOS开发零基础--Swift基础篇--常量&变量的定义
什么是常量和变量 在Swift中规定:在定义一个标识符时必须明确说明该标识符是一个常量还是变量 使用let来定义常量,定义之后不可以修改 使用var来定义变量,定义之后可以修改 常量和变量的使用注意: ...
- 从0开始学Swift笔记整理(四)
这是跟在上一篇博文后续内容: --重写方法 重写实例方法 在子类中重写从父类继承来的实例方法和静态方法.先介绍实例方法的重写. 下面看一个示例: class Person { var n ...
- Android 5.x特性概览五
上节,介绍Material Design 对阴影效果的实现,这节,我们来介绍Android 5.x的着色与裁剪的特性. Android 5.X 在对图像的操作上增加更多的功能,下面来看看 Androi ...
- C#的惰性枚举
Ruby 2.0有一个新的特性是惰性枚举器,Soi Mort 的博客举了一个例子:可以将下面的代码 File.open(path) {|fp| fp.each_line. \ select {|lin ...
- UML中依赖(Dependency)和关联(Association)之间的区别
一般情况下,使用关联(association)来表示像类中的字段等.这个关系是始终存在的,因此你可以随时针对关联项进行访问调用,例如可以始终从 Customer 对象获取 Order 对象.但事实上它 ...
- 作业六—图书管理系统(SPEC)系统性能评估测试
一.图书管理系统的典型用户和场景: 该系统是为各类学校图书馆和社会各大图书馆和书店管理者使用的图书管理系统.但是我们还是已北京工业大学耿丹学院图书馆为典型用户进行主要设计的! 二.SPEC测试的目标: ...