Scala spark中的嵌套循环(评分矩阵分解),如何有效地进行?

Scala spark中的嵌套循环(评分矩阵分解),如何有效地进行?,scala,apache-spark,dataframe,Scala,Apache Spark,Dataframe,我一直在尝试为spark中的一些选定用户生成推荐。这是通过将用户因子(n个浮点向量)与每个乘积因子(n个浮点向量)进行点积来完成的,然后按顺序递减 所以,假设我有客户因素作为(customerId,数组[Float]),我有产品因素作为(productId,数组[Float])。我必须为每个客户创建每个产品的分数,并生成(customerId、productId、score),其中保留每个客户的前N名结果。所以我这样做: val customers = ... // (customerId, A

我一直在尝试为spark中的一些选定用户生成推荐。这是通过将用户因子(n个浮点向量)与每个乘积因子(n个浮点向量)进行点积来完成的,然后按顺序递减

所以,假设我有客户因素作为
(customerId,数组[Float])
,我有产品因素作为
(productId,数组[Float])
。我必须为每个客户创建每个产品的分数,并生成
(customerId、productId、score)
,其中保留每个客户的前N名结果。所以我这样做:

val customers = ... // (customerId, Array[Float])
val products = ... // (productId, Array[Float])
val combination = customers.cartesian(products)
val result = combination.map(x => (combination._1._1, combination._2._1, 
    dotProd(combination._1._2, combination._2._2))

... then filter top N for each customer using dataframe
但这需要花费很多时间,其中一个原因是笛卡尔的结果使数据变得巨大,为每个客户重复相同的产品因素

正如您所看到的,这11 TB的数据用于10万个客户和30万个产品。这是创建的DAG(我做了一个选择,只保留分数的前N个,因此划分):

你有什么建议?如何改进流程以绕过巨大的IO

谢谢

更新 最后,在48个内核上运行这个程序花了10个小时。 还有80 TB的IO!

更新2 我怀疑解决方案是收集并广播两个RDD,在ID上创建笛卡尔坐标,然后查找因子。这将大大减少IO

我将试一试。

[注意:我不会接受我自己的答案,因为这只是一种改进,而不是实质性的改进]

正如我所描述的,我广播了客户和产品因素,这将过程加快了近3倍,并将IO减少到2.4TB

可能会有更多的改进方法,但我想现在还可以

[注意:我不会接受我自己的答案,因为这只是一种改进,而不是实质性的改进]

正如我所描述的,我广播了客户和产品因素,这将过程加快了近3倍,并将IO减少到2.4TB

可能会有更多的改进方法,但我想现在还可以


您的问题在于您正在执行的笛卡尔积。你可以考虑使用LSH这样的近似技术来获得性能。我真的不想接受我自己的答案,因为我对结果不满意。很高兴看到你的建议。你的问题是你正在执行的笛卡尔积。你可以考虑使用LSH这样的近似技术来获得性能。我真的不想接受我自己的答案,因为我对结果不满意。很高兴看到你的建议。