我正在努力优化使用ALS矩阵分解算法执行Collaborative Filtering的Spark集群(在AWS EMR上运行)的性能。我们正在使用相当多的因素和迭代,所以我试图特别优化这些步骤。当我有足够的内存时,我试图理解为什么我使用磁盘空间。以下是可用的总集群内存:
这是剩余的磁盘空间(注意磁盘利用率的下降):
我已经尝试过查看Yarn管理器,看起来它显示每个节点slave都有:110 GB(used)4 GB(avail。)。您还可以在第一张图像(700 GB)上看到分配的总数。我还尝试更改ALS源并强制将intermediateRDDStorageLevel
和finalRDDStorageLevel
从MEMORY_AND_DISK强制转换为MEMORY_ONLY,这不会影响任何内容。
我没有在我的代码中的任何其他位置保留我的RDD,所以我不确定这个磁盘利用率来自何处。我想更好地利用我的集群上的资源,任何想法?如何更有效地使用可用内存?
答案 0 :(得分:3)
可能很少有一些场景,其中spark将使用磁盘使用而不是内存
如果你有洗牌操作。 Spark只会将洗牌后的数据写入磁盘,因此如果您进行了随机播放操作,那么运气不佳
低执行程序内存。如果执行程序内存较少,则内存较少,因此保留数据的内存较少,因此会将数据从内存溢出到磁盘。但是正如您所建议的那样,您已经尝试过从20G到40G的执行程序内存。我建议将执行程序内存保留到40G,因为JVM GC可能会使您的进程变慢。
如果您没有随机播放操作,如果使用spark 2.2,也可以调整spark.memory.fraction
spark.memory.fraction
将M的大小表示为(JVM堆空间 - 300MB)的一小部分(默认值为0.6)。剩下的空间(25%)
保留用户数据结构,Spark中的内部元数据,以及在稀疏和异常情况下防止OOM错误
大记录。
所以你可以将spark.memory.fraction设为.9并查看行为。
MEMORY_ONLY
之外还有其他选项作为MEMORY_ONLY_SER
等存储级别,它将序列化数据并存储在内存中。此选项减少了内存使用量,因为序列化对象大小远小于实际对象大小。如果您发现大量泄漏,可以选择此存储级别。