Spark的快难道是以丧失正确性为代价的?

云计算 Spark
Spark最著名的一篇论文是:《Spark: Cluster Computing with Working Sets》。当你读它的时候你需要明白:文中代码不保证计算结果是正确的。具体来说,它的Logistic Regression的代码在map阶段用到了accumulator。下面解释为什么这么做是错误的。

[[139085]]

是的,Spark很快。但是它不保证它算出的值是对的,哪怕你要做的只是简单的整数累加。

Spark***的一篇论文是:《Spark: Cluster Computing with Working Sets》。当你读它的时候你需要明白:文中代码不保证计算结果是正确的。具体来说,它的Logistic Regression的代码在map阶段用到了accumulator。下面解释为什么这么做是错误的。

假设有这样一个简单的任务:

input file的每一行是100个整数,要求竖着加下来

例如:

输入

1 2 3 4 5 ... 100

1 2 3 4 5 ... 200

1 3 3 4 5 ... 100

输出

3 7 9 12 15 ... 400

很简单,对吧?是个猪都会算。在hadoop上这个问题可以通过Map reduce来解决。首先把输入文件分成N个大小相等的块。然后每个块输出一行100个整数,如 2 4 6 8 10 ... 200

然后reducer接收每个mapper的输出结果,累加起来得到最终结果。

缺点是: 从mapper到reducer是需要DISK-IO及网络传输的。那么需要传输N*100个整数。当输入集的维数很大(每行有上百万个字节)的时候,很浪费。

spark很巧妙的引入了accumulator的概念。同一台机器上所有的task的输出,会先在这个机器上进行本地汇总,然后再发给 reducer。这样就不再是task数量*维数,而是机器数量*维数。会节省不少。具体来说,在做机器学习的时候,大家很习惯的用 accumulator来做这样的计算。

accumulator是被很careful设计的。比如,只有master节点能读取accumulator的值,worker节点不能。在“Performance and Scalability of Broadcast in Spark

”一文中,作者写到:“Accumulators can be defined for any type that has an “add” operation and a “zero” value. Due to their “add-only” semantics, they are easy to make fault-tolerant.” 。但真的是这样吗?并不是。

accumulator如果不是运行在运算的***一环,那么正确性无法保证。因为accumulator不是map/reduce函数的输入或输出,accumulator是表达式求值中的side-effect。举个例子:

  1. val acc = sc.accumulator(0
  2.  
  3. data.map(x => acc += 1; f(x)) 
  4.  
  5. data.count() 
  6.  
  7. // acc should equal data.count() here 
  8.  
  9. data.foreach{...} 
  10.  
  11. // Now, acc = 2 * data.count() because the map() was recomputed. 

这个问题被spark的创始人Matei标为Won't Fix。

那么是不是写代码小心点不要触发重复计算就行了呢?也不是。task是有可能fail-retry的,再或者因为某一个task执行的慢,所以同时有它的多个副本在跑。这些都可能会导致accumulator结果不正确。 Accumulators只能用在RDD的actions中,不能用在Transformations。举例来说:可以在reduce函数中用,但是不能在map函数中用。

如果不用accumlators,但又想节省网络传输,那么Matei说:“I would suggest creating fewer tasks. If your input file has a lot of blocks and hence a lot of parallel tasks, you can use CoalescedRDD to create an RDD with fewer blocks from it. ”

意思就是说,那你就把task划分大一点,把task的数量减少。比如每台机器只有1个task。 Downside其实也很明显,任务的执行容易不balance。

参考: https://issues.apache.org/jira/browse/SPARK-732

https://issues.apache.org/jira/browse/SPARK-3628

https://issues.apache.org/jira/browse/SPARK-5490

https://github.com/apache/spark/pull/228

原文链接:http://www.sunchangming.com/blog/post/4672.html
 

责任编辑:Ophira 来源: 个人博客
相关推荐

2011-04-19 09:41:22

数据库

2024-01-06 08:10:08

ChatGPT-4人工智能知识图谱

2017-06-23 08:45:02

存储技术复杂性

2010-02-25 16:22:18

Linux gcc编译

2017-06-05 16:17:50

深度学习算法神经网络

2018-12-18 17:45:59

数据库数据库安全

2024-01-23 11:22:53

谷歌大语言模型AI

2017-10-12 11:30:34

Spark代码PR

2022-11-21 16:10:31

奔驰可靠性排名

2014-12-08 10:37:54

HTTPS

2022-11-29 07:14:56

NLP语言模型

2018-12-17 13:38:13

隐私人力资源物联网

2021-12-29 22:50:24

5GWiFi路由器

2019-07-22 10:45:31

2014-06-05 08:47:52

Spark 1.0Mapreduce

2023-07-06 15:49:32

CIOAI

2021-07-02 10:02:03

勒索软件攻击数据泄露

2016-11-14 14:29:14

C语言

2014-11-04 13:43:10

2013-06-13 13:19:38

多线程
点赞
收藏

51CTO技术栈公众号