我有一个火花工作,它在隐式反馈等级矩阵上执行Alternating Least Squares (ALS)。我按如下方式创建ALS对象。
val als = new ALS()
.setCheckpointInterval(5)
.setRank(150)
.setAlpha(30.0)
.setMaxIter(25)
.setRegParam(0.001)
.setUserCol("userId")
.setItemCol("itemId")
.setRatingCol("rating")
.setImplicitPrefs(true)
.setIntermediateStorageLevel("MEMORY_ONLY")
.setFinalStorageLevel("MEMORY_ONLY")
将创建评级矩阵,并将其用于拟合ALS模型,如下所示。
val ratingsSchema = StructType(Array(
StructField("userId", IntegerType, nullable = true),
StructField("itemId", IntegerType, nullable = true),
StructField("rating", DoubleType, nullable = true)))
val ratings = spark
.read
.format("parquet")
.schema(ratingsSchema)
.load("/ratings")
.cache()
val model = als.fit(ratings)
ratings
DataFrame中大约有1.5亿个唯一用户和100万个项目,其中有大约8.5亿行。
基于上述数字,满载时,额定DataFrame应在内存中占据约20 GB的空间。 userFactors数据帧将为150 MM x 150倍= 180 GB(大约)。 itemFactors数据框应仅为1.2GB。
完成这项工作需要很长时间(超过15小时)。我的群集规格如下。
Provider: AWS EMR version 5.14.0
Spark version: 2.3.0
Cluster:
1 MASTER node: m4.xlarge (8 cores, 16GB mem, 32GB storage)
2 CORE nodes: i3.xlarge (4 cores, 30GB mem, 950 GB storage)
20 TASK nodes: r4.4xlarge (16 cores, 122GB mem, 32 GB storage)
Total TASK cores = 320
Total TASK memory: 2440 GB
根据上述数字,所有DF都应轻松放入内存中(如果需要,还可以使用TB + HDFS)。
作业配置:
--executor-memory 102g
--num-executors 20
--executor-cores 15
我可以看到有20个执行程序正在运行(还有一个驱动程序)。我尝试过缓存DF,也没有缓存。
如果可能,如何调整系统以使其运行更快?
有人对ALS job有见识吗?它会产生很多改组吗?我们如何才能最大程度地减少混洗?
评分矩阵采用parquet
格式,其中200个文件存储在S3的存储桶中。
如果我有很多小型实例(例如50个),还是应该得到几个(例如5个)非常大的实例(如r4.16xlarge(64核,488GB内存)),效果会更好?