我正在使用Google dataflow + Scio进行数据集与其自身的交叉联接,以通过进行余弦相似度来找出topK最相似的数据集。数据集大约有20万条记录,数据集的总大小约为300MB。
我通过将workerCacheMB设置为500MB来作为侧面输入将数据集与自身连接起来。
数据集是一个元组,它看起来像这样:(String,Set(Integer))。元组中的第一个元素是URI,下一个元素是一组实体索引。
数据集中的大多数记录具有500个以下的实体索引。但是,大约有7,000条记录,其中有超过1万个实体,最多有171k个实体。
扩展到80个节点然后缩减到1个节点后,它已经处理了大约90%的记录。我认为,热键卡在了最后一个节点上,剩下的时间都花在了处理所有热键上。
我尝试了--experiments=shuffle_mode=service
选项。尽管它有所改进,但问题仍然存在。我在考虑使用here中提到的分片式HotKey连接的方法,但是自从我需要找到相似性以来,我觉得我承受不起拆分热实体并重新加入它们的负担。
我想知道是否有办法解决它,或者我是否基本上必须忍受这个问题。 显然,这是查找模拟市民的粗略方法。但是,我有兴趣为问题的数据工程部分找到解决方案,同时让ML工程师迭代Sim查找算法。
简化后的代码如下:
private def findSimilarities(e1: Set[Integer], e2: Set[Integer]): Float = {
val common = e1.intersect(e2)
val cosine = (common.size.toFloat) / (e1.size + e2.size).toFloat
cosine
}
val topN = sortedReverseTake[ElementSims](250)(by(_.getScore))
elements
.withSideInputs(elementsSI)
.flatMap { case (e1, si) =>
val fromUri = e1._1.toString
val fromEntities = e1._2
val sideInput: List[(String, Set[Integer])] = si(elementsSI)
val sims: List[ElementSims] = findSimilarities(fromUri,fromEntities,
sideInput)
topN(sims)
}
.toSCollection
.saveAsAvroFile(outputGCS)