【发布时间】:2015-04-10 21:30:04
【问题描述】:
我用一些随机数学值填充 RDD:
val itemFactors = rddItems.mapValues(newFactors =>
Vector(Array.fill(2){math.random})
)
然后我将该 RDD 加入到其他 RDD 并缓存它:
val finalRDD = itemFactors.join(rddItemsUsers).map{
case(itemid, (itemVector, ((userid, rating), userVector))) =>
(itemid, itemVector, userid, userVector, rating)}.cache
然后我对finalRDD中保存的数据进行计算:
sqrt(finalRDD.aggregate(0.0)((accum, item) =>
accum + pow(item._5 - item._4.dot(item._2), 2), _ + _) / finalRDD.count)
我从控制台反复调用代码的最后一部分sqrt(...),每次我得到不同的结果 - 这是不希望的,因为我没有改变任何东西!这可以通过 2 种方式进行补救(即,使我得到一致的结果):
我可以用固定数字填充数组,而不是用
itemFactors初始化math.random,例如1.0我可以
itemFactors.cache。
现在,我了解到,由于血统,每次调用 itemFactors 时,它都会调用 math.random 并创建一个新数字 - 因此,这将影响我的计算。这就是为什么在填充数组时使用固定数字会产生一致的结果。
但是,最大的问题和我不明白的一点是:我正在缓存 finalRDD,这是计算所执行的,因为它由 itemFactors 组成,所以肯定没关系itemFactor 的数组被填充了,因为节点只被访问过一次?我以为我开始掌握传承;但是,这让我很震惊。
【问题讨论】:
-
cache()不能保证它总是被缓存——例如你有足够的内存来保存它吗?它的缓存百分比是多少?如果你丢失了一个块,它也会重新计算。 -
不太清楚如何检查,但我检查了
getStorageLevel,我得到:StorageLevel(false, true, false, true, 1)。如果我这样做getStorageLevel.description,我会得到:Memory Deserialized 1x Replicated。getStorageLevel.useMemory返回True -
你能把它做成一个可重现的例子吗?我不知道
rddItems和rddItemsUsers中有什么。可能是侏儒。 -
您可以在 UI 的存储选项卡上查看缓存的分数。
-
我将尽快制作一个可重现的示例。感谢您的 UI 提示。
标签: apache-spark rdd