记一次spark mllib stackoverflow踩坑

以前做als相关的东西的时候,都是用的公司的内部工具居多,今天第一次用了下spark的mlib,拿了个几M的小数据集试了个水。。

结果一跑,我擦。。。居然stackoverflow了。。


源码如下:

from pyspark.mllib.recommendation import ALS
from numpy import array
from pyspark import SparkContext

if __name__ == '__main__':
	# sc = SparkSession\
	# 	.builder\
	# 	.appName("PythonWordCount")\
	# 	.getOrCreate()
	sc = SparkContext(appName="PythonWordCount")

	data = sc.textFile("CollaborativeFiltering.txt", 20)
	ratings = data.map(lambda line: [float(x) for x in line.split(' ')]).persist()
	rank = 10
	n = 30

	model = ALS.train(ratings, rank, n)
	testdata = ratings.map(lambda r: (int(r[0]), int(r[1])))
	predictions = model.predictAll(testdata).map(lambda r: ((r[0], r[1]), r[2]))

	ratesAndPreds = ratings.map(lambda r: ((r[0], r[1]), r[2])).join(predictions).persist()
	MSE = ratesAndPreds.map(lambda r: (r[1][0] - r[1][1])**2).reduce(lambda x, y: x + y)/ratesAndPreds.count()

	print "Mean Squared Error = " + str(MSE)
	ratesAndPreds.unpersist()

错误信息如下:

2017-11-24 17:15:23 [INFO] ShuffleMapStage 66 (flatMap at ALS.scala:1272) failed in Unknown s due to Job aborted due to stage failure: Task serialization failed: java.lang.StackOverflowError
java.lang.StackOverflowError
    at java.io.ObjectOutputStream$BlockDataOutputStream.write(ObjectOutputStream.java:1841)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1534)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
    at scala.collection.immutable.$colon$colon.writeObject(List.scala:379)
    at sun.reflect.GeneratedMethodAccessor15.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:1028)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)


一开始以为是join的问题,查了好久,无果,又怀疑是jvm设置的问题。。。很显然也没有进展。。

泪崩 + 泪崩 + 泪崩

再后来怀疑到了linage 是不是过长导致,遂google和请教大神



发现果然如此,spark在迭代计算的过程中,会导致linage剧烈变长,所需的栈空间也急剧上升,最终爆栈了。。

这类问题解决方法如下:

在代码中加入 sc.setCheckpointDir(path),显示指明checkpoint路径,问题便可得到解决。当然这也带来了一个问题,如果数据量变大,磁盘的IO变成为了瓶颈,这方面暂时没能解决,各位聚聚有更好的解决方案,欢迎联系我~

修改后代码如下:

from pyspark.mllib.recommendation import ALS
from numpy import array
from pyspark import SparkContext

if __name__ == '__main__':
	# sc = SparkSession\
	# 	.builder\
	# 	.appName("PythonWordCount")\
	# 	.getOrCreate()
	sc = SparkContext(appName="PythonWordCount")
	sc.setCheckpointDir('checkpoint')
	data = sc.textFile("CollaborativeFiltering.txt", 20)
	ratings = data.map(lambda line: [float(x) for x in line.split(' ')]).persist()
	rank = 10
	n = 30
	#ALS.setCheckpointInterval(2).setMaxIter(100).setRank(10).setAlpha(0.1)
	model = ALS.train(ratings, rank, n)
	testdata = ratings.map(lambda r: (int(r[0]), int(r[1])))
	predictions = model.predictAll(testdata).map(lambda r: ((r[0], r[1]), r[2]))

	ratesAndPreds = ratings.map(lambda r: ((r[0], r[1]), r[2])).join(predictions).persist()
	MSE = ratesAndPreds.map(lambda r: (r[1][0] - r[1][1])**2).reduce(lambda x, y: x + y)/ratesAndPreds.count()

	print "Mean Squared Error = " + str(MSE)
	ratesAndPreds.unpersist()


  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
### 回答1: Java.lang.StackOverflowError是Java虚拟机在执行程序时遇到的一种错误,通常是由于递归调用导致的。解决方法如下: 1.检查代码中是否存在无限递归调用的情况,如果有,需要修改代码。 2.增加堆栈大小,可以通过设置JVM参数-Xss来增加堆栈大小,例如:java -Xss2m Main。 3.优化代码,减少递归调用的深度,可以使用循环代替递归。 4.使用尾递归优化,将递归调用转换为迭代调用,可以避免栈溢出的问题。 5.使用非递归算法,避免使用递归算法,可以避免栈溢出的问题。 6.升级JVM版本,如果是JVM版本的问题,可以升级JVM版本来解决问题。 ### 回答2: Spark是一个大数据处理框架,其底层实现涉及到大量的递归算法,因此在处理大量数据的情况下,容易出现java.lang.stackoverflowerror错误。下面是一些可能的解决方法: 1.增加JVM堆栈大小 由于大多数情况下java.lang.stackoverflowerror错误是由于线程占用堆栈空间过多导致的,因此可以通过增加JVM堆栈大小来解决该错误。通过设置JVM参数-Xss,可以增加堆栈大小。例如,将-Xss设置为4m,则堆栈大小为4MB。需要注意的是,过大的堆栈大小可能会降低整体性能并增加资源消耗。 2.优化代码 优化代码可以减少递归算法的使用,在处理大数据量时可能会降低出错率。例如,可以使用迭代算法代替递归算法,或者使用尾递归优化。 3.增加可用CPU资源 由于Spark处理大数据通常需要使用多个线程,因此增加可用CPU资源可以减少java.lang.stackoverflowerror错误的发生。例如,可以增加Spark集群中的计算节点数量或增加每个节点上的CPU核心数量。 4.更换硬件设备 在处理大数据量和高并发量的情况下,硬件设备可能成为瓶颈,导致java.lang.stackoverflowerror错误的发生。因此,更换更强大的硬件设备可以有效地解决该问题。 总之,解决java.lang.stackoverflowerror错误有多种方法,要根据具体情况选择合适的解决方案。在实际应用中,应该综合考虑效率、资源占用、可维护性等因素,从而达到最佳的解决方案。 ### 回答3: 在使用Spark进行大数据处理时,有时会出现java.lang.stackoverflowerror错误。这个错误通常是由递归方法调用过多造成的。 为了解决这个问题,我们可以采取以下方法: 1. 增加JVM内存分配:可以通过在启动Spark时增加JVM内存分配来解决这个问题。可以通过--driver-memory 或者 --executor-memory 来配置分配的内存大小。 2. 优化代码:检查代码中是否存在过多的递归方法调用。可以采用迭代的方式代替递归,或者增加递归深度限制等方法来降低递归深度。 3. 优化数据处理:检查数据处理方式是否合理,是否存在过多的迭代或者递归处理。可以采用分布式处理或者MapReduce等方法将数据拆分为小批次进行处理。 4. 使用栈深度调整参数:对于JVM中的递归方法调用栈,可以适当调整栈深度参数来解决StackOverflowError错误。可以通过-Xss参数来调整栈深度大小。 总的来说,解决java.lang.stackoverflowerror错误需要综合考虑代码质量、数据处理方式以及JVM内存分配等方面。只有在综合考虑并进行优化后,才能有效避免这个问题的出现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值