scala – 如何从任务中打印累加器变量(似乎“工作”而不调用值方
我知道累积器变量从任务的角度来看是“只写”的,当它们在工作节点中执行时.我正在对此进行一些测试,我意识到我能够在任务中打印累加器值.
我在这里初始化驱动程序中的累加器: – scala> val accum = sc.accumulator(123) accum: org.apache.spark.Accumulator[Int] = 123 然后我继续定义一个函数’foo’: – scala> def foo(pair:(String,String)) = { println(accum); pair } foo: (pair: (String,String))(String,String) 在这个函数中,我只是打印累加器,然后返回收到的同一对. 现在我有一个名为myrdd的RDD,其类型如下: – scala> myrdd res13: org.apache.spark.rdd.RDD[(String,String)] = MapPartitionsRDD[9] at map at <console>:21 我现在正在调用这个RDD上的地图转换: – myrdd.map(foo).collect “收集”行动正在应用于强制评估.所以这里实际发生的是,在执行期间,为RDD的每一行打印零(0).由于这个RDD有4个元素,它打印0次4次.由于动作’collect’在那里,它也会打印出最后的所有元素,但这并不是真正的重点.所以我有两个问题: – >从逻辑上讲,打印相当于阅读,因为只有当你能阅读时,才能打印.那么为什么允许这样做呢?如果我们试图在函数中“返回”累加器,为什么不会抛出异常会发生的事情? 经过一些实验,我发现如果我改变函数定义来访问累加器对象的实际值属性(accum.value),然后按照已经描述的那样触发RDD动作,它确实抛出异常: – scala> def foo(pair:(String,String)) = { println(accum.value); pair } RDD评估期间引起的例外: –
所以我之前做的是尝试打印累加器对象本身.但问题仍然是为什么它打印0?因为在驱动程序级别,如果我发出了我在函数定义中使用的相同命令,我确实得到了值123: – scala> println(accum) 123 我没有必要说println(accum.value)才能正常工作.那么为什么只有当我在任务使用的函数中发出此命令时,它是否打印0? 解决方法
因为工作节点永远不会看到初始值.只有传递给worker的东西是零,如AccumulatorParam中所定义的那样.对于Accumulator [Int],它只是0.如果你第一次更新累加器,你会看到更新的本地值: val acc = sc.accumulator(123) val rdd = sc.parallelize(List(1,2,3)) rdd.foreach(i => {acc += i; println(acc)}) 使用单个分区时更清楚: rdd.repartition(1).foreach(i => {acc += i; println(acc)}
因为访问 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |