如何在不耗尽内存的情况下运行大型 Mahout 模糊 kmeans 聚类?

Posted

技术标签:

【中文标题】如何在不耗尽内存的情况下运行大型 Mahout 模糊 kmeans 聚类?【英文标题】:How to run large Mahout fuzzy kmeans clustering without running out of memory? 【发布时间】:2013-04-13 08:20:28 【问题描述】:

我在 Amazon 的 EMR (AMI 2.3.1) 上运行 Mahout 0.7 模糊 k 均值集群,并且 我的内存快用完了。

我的总体问题:如何最轻松地让它工作?

这是一个调用:

./bin/mahout fkmeans \
  --input s3://.../foo/vectors.seq \
  --output s3://.../foo/fuzzyk2 \
  --numClusters 128 \
  --clusters s3://.../foo/initial_clusters/ \
  --maxIter 20 \
  --m 2 \
  --method mapreduce \
  --distanceMeasure org.apache.mahout.common.distance.TanimotoDistanceMeasure

更详细的问题:

如何知道我正在使用多少内存?我在 c1.xlarge 实例上。如果我相信AWS docs,那就设置mapred.child.java.opts=-Xmx512m。

如何知道我需要多少内存?我可以尝试不同的大小,但这让我不知道我可以处理的问题的大小。

如何更改内存使用情况?使用不同类别的机器启动不同的工作流程?尝试设置 mapred.child.java.opts?

我的数据集似乎没有那么大。是吗?

vectors.seq 是具有 50225 个向量的稀疏向量的集合 (50225 个事物与 124420 个其他事物相关),总共 120 万个关系。

This post 说 set --method mapreduce,我是,哪个是 默认。

This post 表示所有集群都保存在每个映射器的内存中,并且 减速器。那将是 4*124420=498K 的东西,这似乎不太 不好。

这是堆栈:

13/04/19 18:12:53 INFO mapred.JobClient: Job complete: job_201304161435_7034
13/04/19 18:12:53 INFO mapred.JobClient: Counters: 7
13/04/19 18:12:53 INFO mapred.JobClient:   Job Counters 
13/04/19 18:12:53 INFO mapred.JobClient:     SLOTS_MILLIS_MAPS=28482
13/04/19 18:12:53 INFO mapred.JobClient:     Total time spent by all reduces waiting after reserving slots (ms)=0
13/04/19 18:12:53 INFO mapred.JobClient:     Total time spent by all maps waiting after reserving slots (ms)=0
13/04/19 18:12:53 INFO mapred.JobClient:     Rack-local map tasks=4
13/04/19 18:12:53 INFO mapred.JobClient:     Launched map tasks=4
13/04/19 18:12:53 INFO mapred.JobClient:     SLOTS_MILLIS_REDUCES=0
13/04/19 18:12:53 INFO mapred.JobClient:     Failed map tasks=1
Exception in thread "main" java.lang.InterruptedException: Cluster Iteration 1 failed processing s3://.../foo/fuzzyk2/clusters-1
        at org.apache.mahout.clustering.iterator.ClusterIterator.iterateMR(ClusterIterator.java:186)
        at org.apache.mahout.clustering.fuzzykmeans.FuzzyKMeansDriver.buildClusters(FuzzyKMeansDriver.java:288)
        at org.apache.mahout.clustering.fuzzykmeans.FuzzyKMeansDriver.run(FuzzyKMeansDriver.java:221)
        at org.apache.mahout.clustering.fuzzykmeans.FuzzyKMeansDriver.run(FuzzyKMeansDriver.java:110)
        at org.apache.hadoop.util.ToolRunner.run(ToolRunner.java:65)
        at org.apache.mahout.clustering.fuzzykmeans.FuzzyKMeansDriver.main(FuzzyKMeansDriver.java:52)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.apache.hadoop.util.ProgramDriver$ProgramDescription.invoke(ProgramDriver.java:68)
        at org.apache.hadoop.util.ProgramDriver.driver(ProgramDriver.java:139)
        at org.apache.mahout.driver.MahoutDriver.main(MahoutDriver.java:195)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.apache.hadoop.util.RunJar.main(RunJar.java:187)

这是映射器日志的一部分:

2013-04-19 18:10:38,734 INFO org.apache.hadoop.fs.s3native.NativeS3FileSystem (main): Received IOException while reading '.../foo/vectors.seq', attempting to reopen.
java.net.SocketTimeoutException: Read timed out
        at java.net.SocketInputStream.socketRead0(Native Method)
        at java.net.SocketInputStream.read(SocketInputStream.java:129)
        at com.sun.net.ssl.internal.ssl.InputRecord.readFully(InputRecord.java:293)
        at com.sun.net.ssl.internal.ssl.InputRecord.readV3Record(InputRecord.java:405)
        at com.sun.net.ssl.internal.ssl.InputRecord.read(InputRecord.java:360)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:798)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:755)
        at com.sun.net.ssl.internal.ssl.AppInputStream.read(AppInputStream.java:75)
        at org.apache.http.impl.io.AbstractSessionInputBuffer.read(AbstractSessionInputBuffer.java:187)
        at org.apache.http.impl.io.ContentLengthInputStream.read(ContentLengthInputStream.java:164)
        at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:138)
        at java.io.FilterInputStream.read(FilterInputStream.java:116)
        at org.apache.hadoop.fs.s3native.NativeS3FileSystem$NativeS3FsInputStream.read(NativeS3FileSystem.java:291)
        at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
        at java.io.BufferedInputStream.read1(BufferedInputStream.java:258)
        at java.io.BufferedInputStream.read(BufferedInputStream.java:317)
        at java.io.DataInputStream.readFully(DataInputStream.java:178)
        at org.apache.hadoop.io.DataOutputBuffer$Buffer.write(DataOutputBuffer.java:63)
        at org.apache.hadoop.io.DataOutputBuffer.write(DataOutputBuffer.java:101)
        at org.apache.hadoop.io.SequenceFile$Reader.next(SequenceFile.java:2060)
        at org.apache.hadoop.io.SequenceFile$Reader.next(SequenceFile.java:2194)
        at org.apache.hadoop.mapreduce.lib.input.SequenceFileRecordReader.nextKeyValue(SequenceFileRecordReader.java:68)
        at org.apache.hadoop.mapred.MapTask$NewTrackingRecordReader.nextKeyValue(MapTask.java:540)
        at org.apache.hadoop.mapreduce.MapContext.nextKeyValue(MapContext.java:67)
        at org.apache.hadoop.mapreduce.Mapper.run(Mapper.java:143)
        at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:771)
        at org.apache.hadoop.mapred.MapTask.run(MapTask.java:375)
        at org.apache.hadoop.mapred.Child$4.run(Child.java:255)
        at java.security.AccessController.doPrivileged(Native Method)
        at javax.security.auth.Subject.doAs(Subject.java:396)
        at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1132)
        at org.apache.hadoop.mapred.Child.main(Child.java:249)
2013-04-19 18:10:38,737 INFO org.apache.hadoop.fs.s3native.NativeS3FileSystem (main): Stream for key '.../foo/vectors.seq' seeking to position '62584'
2013-04-19 18:10:42,619 INFO org.apache.hadoop.mapred.TaskLogsTruncater (main): Initializing logs' truncater with mapRetainSize=-1 and reduceRetainSize=-1
2013-04-19 18:10:42,730 INFO org.apache.hadoop.io.nativeio.NativeIO (main): Initialized cache for UID to User mapping with a cache timeout of 14400 seconds.
2013-04-19 18:10:42,730 INFO org.apache.hadoop.io.nativeio.NativeIO (main): Got UserName hadoop for UID 106 from the native implementation
2013-04-19 18:10:42,733 FATAL org.apache.hadoop.mapred.Child (main): Error running child : java.lang.OutOfMemoryError: Java heap space
        at org.apache.mahout.math.map.OpenIntDoubleHashMap.rehash(OpenIntDoubleHashMap.java:434)
        at org.apache.mahout.math.map.OpenIntDoubleHashMap.put(OpenIntDoubleHashMap.java:387)
        at org.apache.mahout.math.RandomAccessSparseVector.setQuick(RandomAccessSparseVector.java:139)
        at org.apache.mahout.math.AbstractVector.assign(AbstractVector.java:560)
        at org.apache.mahout.clustering.AbstractCluster.observe(AbstractCluster.java:253)
        at org.apache.mahout.clustering.AbstractCluster.observe(AbstractCluster.java:241)
        at org.apache.mahout.clustering.AbstractCluster.observe(AbstractCluster.java:37)
        at org.apache.mahout.clustering.classify.ClusterClassifier.train(ClusterClassifier.java:158)
        at org.apache.mahout.clustering.iterator.CIMapper.map(CIMapper.java:55)
        at org.apache.mahout.clustering.iterator.CIMapper.map(CIMapper.java:18)
        at org.apache.hadoop.mapreduce.Mapper.run(Mapper.java:144)
        at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:771)
        at org.apache.hadoop.mapred.MapTask.run(MapTask.java:375)
        at org.apache.hadoop.mapred.Child$4.run(Child.java:255)
        at java.security.AccessController.doPrivileged(Native Method)
        at javax.security.auth.Subject.doAs(Subject.java:396)
        at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1132)
        at org.apache.hadoop.mapred.Child.main(Child.java:249)

【问题讨论】:

【参考方案1】:

是的,您的内存不足。据我所知,“内存密集型工作负载”引导操作早已被弃用,因此可能什么也不做。请参阅该页面上的注释。

默认情况下,c1.xlarge 应使用 384MB per mapper。当您减去所有 JVM 开销、拆分和合并的空间等时,您可能已经没有太多剩余了。

您在引导操作中设置 Hadoop 参数。如果使用控制台并设置类似 --site-key-value mapred.map.child.java.opts=-Xmx1g 的内容,请选择“配置 Hadoop”操作

(如果您以编程方式执行此操作,并且遇到任何问题,请离线联系我;我可以通过Myrrix 提供 sn-ps,因为它会大量调整 EMR 集群以提高其推荐/集群作业的速度。 )

您可以设置mapred.map.java.child.opts 来分别控制映射器和reducer。您还可以减少每台机器的映射器数量以腾出更多空间,或者选择高内存实例。我通常发现ml.xlarge 是 EMR 的最佳选择,因为价格与 I/O 的比率,而且因为大多数作业最终都受 I/O 限制。

【讨论】:

谢谢。知道如何计算我需要多少内存吗? 4*(簇向量中的#个条目)*某事? 我对这段代码没有任何经验。我猜你需要假设 20% 的堆需要保持空闲,100MB 用于洗牌/溢出,然后猜测其余的可能可用。一个向量可能需要……每个条目 20 个字节?这可能会让你接近。通常你首先会在 I/O 上遇到瓶颈,所以我将它调高到 1GB,并且每台机器可能只允许 4 个映射器,看看你是否还没有受到 CPU 限制。 谢谢。所以 4 *(100000 个条目)*(20 字节/条目)*(128 个簇)= 1.024G。这个算法是一个内存猪。 我不知道这段代码是如何工作的。我这样做的方式只将集群质心保存在内存中,这可以忽略不计。

以上是关于如何在不耗尽内存的情况下运行大型 Mahout 模糊 kmeans 聚类?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不耗尽内存的情况下制作大型 3D 数组?

如何使用 Python Ray 在不耗尽内存的情况下并行处理大量数据?

如何在不使用太多内存的情况下强制下载大文件?

如何在不耗尽内存的情况下部署包含 130,000 多个条目的脚本

在不耗尽内存的情况下检索图像

如何在不复制的情况下在多个进程中使用大型数据集?