[0.2]从Scala语言层面体验Spark的计算魅力
2016-05-28 12:19
399 查看
参考
CollectionsStream API
Memoization技术详解
场景
Spark RDD相当于一个分布式的scala集合,而Spark本身是用scala写的。本文尝试以集合元素scala.collection.immutable.Stream的使用为例,从scala语言层面内置的延迟计算与Memoization体验Spark强大的计算能力!关于延迟计算
延迟计算能避免计算中间结果的产生,在一些计算中间过程很复杂或者很漫长的程序中,最能体现延迟计算的功力。scala中以 lazy关键字修饰的实体都具有延迟计算的特性。
关于memoization
memoization是一种可以缓存之前运算结果的技术,这样我们就不需要重新计算那些已经计算过的结果。
认识Stream类
本文以scala.collection.immutable.Stream类使用,通过实验来体验lazy与memoization的魅力。一句话介绍Stream:“Stream implements lazy lists where elements are only evaluated when they are needed.” ,简单来说就相当于 lazy 版的scala.collection.immutable.List .
这篇文章的编写纯属意外:学习Stream类的操作时发现滴!哈哈!
实验
Stream初探
Stream的创建:scala> val strm = 1#::2#::Stream.empty strm: scala.collection.immutable.Stream[Int] = Stream(1, ?) scala> (1 to 100).toStream.map(i=> i*3+7).filter(i=> (i%10)==0).sum res6: Int = 1450 scala>
以打印‘斐波那契数列’前7项为例,用两种方式实现,进一步认识Stream:
- def 版实现
scala> def fibs(a:BigInt,b:BigInt):Stream[BigInt]=a#::fibs(b,a+b) fibs: (a: BigInt, b: BigInt)Stream[BigInt] scala> fibs(0,1) take 7 foreach println 0 1 1 2 3 5 8 scala>
val 版实现(好神奇的实现方式啊-目前还未完全理解)
scala> val fibs:Stream[BigInt]=BigInt(0)#::BigInt(1)#::fibs.zip(fibs.tail).map(n=>n._1 +n._2) fibs: Stream[BigInt] = Stream(0, ?) scala> fibs(7) res4: BigInt = 13 scala> fibs take 7 foreach println 0 1 1 2 3 5 8 scala>
延迟计算
“The class ” scala.collection.immutable.Stream 相当于 lazy版的scala.collection.immutable.List。这里以Stream的使用为例,加以说明lazy的魅力!:scala> Range(1,50000000).filter(_%2==0)(1) java.lang.OutOfMemoryError: GC overhead limit exceeded
scala> Stream.range(1,50000000).filter(_%2==0)(1) res44: Int = 4 //1至50000000内第二个能被2整除的整数
语句:
Range(1,50000000).filter(_%2==0)(1)的执行直接导致了OOM!而语句:
Stream.range(1,50000000).filter(_%2==0)(1)则正确计算了结果!?因为
Stream.range(1,50000000)并没有把50000000内所有的整数都列出来:
scala> Stream.range(1,50000000) res3: scala.collection.immutable.Stream[Int] = Stream(1, ?)
而语句:
Stream.range(1,50000000).filter(_%2==0)也只执行了第一小步:
scala> Stream.range(1,50000000).filter(_%2==0) res5: scala.collection.immutable.Stream[Int] = Stream(2, ?)
memoization
memoization是一种可以缓存之前运算结果的技术,这样我们就不需要重新计算那些已经计算过的结果。Mr.Snail猜想Stream内部就使用了memoization技术,来提高迭代计算的速度。 这里以求第十二个斐波那契数为例,加以说明!scala> val fibs:Stream[BigInt]=BigInt(0)#::BigInt(1)#::fibs.zip(fibs.tail).map(n=>{println("Adding %d and %d".format(n._1,n._2));n._1+n._2}) fibs: Stream[BigInt] = Stream(0, ?) scala> fibs(5) Adding 0 and 1 Adding 1 and 1 Adding 1 and 2 Adding 2 and 3 res9: BigInt = 5 scala> fibs(10) Adding 3 and 5 Adding 5 and 8 Adding 8 and 13 Adding 13 and 21 Adding 21 and 34 res10: BigInt = 55 scala> fibs(12) Adding 34 and 55 Adding 55 and 89 res11: BigInt = 144
这里由于前面计算过 第10个斐波那契数,计算第12个直接在前面计算的基础上(使用Memoization技术缓存了之前运算结果),而不是再从头开始计算,所以效率极高!
总结
scala中引入了函数式编程的一些精髓:lazy、momoization等,这使其在处理一些计算场景,eg、迭代计算,具有很高的效率 -大数据计算框架Spark在很大程度上得意于scala语言本身的优良特性。相关文章推荐
- Tomcat下log4j设置文件路径和temp目录
- 文件的拆分与合并
- HDU 2577---How to Type
- 350. Intersection of Two Arrays II
- 1026. 程序运行时间(15)
- Python学习路程day15
- 如何设计百度 豆丁 道客巴巴 下载器
- 记录脑残失误,让达摩克利斯之剑永远高悬
- 剑指offer(三十五)之确定两串乱序同构
- Java之JVM虚拟机理解和实例
- 推荐几种PHP实现页面跳转的方法
- hdu 1074 doing homework
- CStdioFile类建立日志记录文件
- 2.1.4 uboot的工作方式
- 修改源码,自定义chromium启动页
- ie调试器
- 3611: [Heoi2014]大工程
- 勺子难免碰锅沿,不咬舌怎么读θ和ð?
- 2.1.3 uboot必须解决哪些问题?
- LeetCode:Count Primes