繁体   English   中英

Spark 创建 numpy 数组的 RDD 的最快方法

[英]Spark fastest way for creating RDD of numpy arrays

我的 spark 应用程序使用的是 numpy 数组的 RDD。
目前,我正在从 AWS S3 读取我的数据,并将其表示为一个简单的文本文件,其中每一行都是一个向量,每个元素用空格分隔,例如:

1 2 3
5.1 3.6 2.1
3 0.24 1.333

我正在使用 numpy 的函数loadtxt()来从中创建一个 numpy 数组。
但是,这种方法似乎很慢,而且我的应用程序花费了太多时间(我认为)将我的数据集转换为 numpy 数组。

你能建议我一个更好的方法吗? 例如,我应该将数据集保留为二进制文件吗?我应该以另一种方式创建 RDD 吗?

关于如何创建 RDD 的一些代码:

data = sc.textFile("s3_url", initial_num_of_partitions).mapPartitions(readData)

读取数据功能:

 def readPointBatch(iterator):
     return [(np.loadtxt(iterator,dtype=np.float64)]

简单地使用numpy.fromstring进行映射会更惯用,速度也稍快,如下所示:

import numpy as np.

path = ...
initial_num_of_partitions = ...

data = (sc.textFile(path, initial_num_of_partitions)
   .map(lambda s: np.fromstring(s, dtype=np.float64, sep=" ")))

但是忽略了你的方法没有什么特别的错误。 据我所知,使用基本配置,读取数据的速度大约是简单读取数据的两倍,比创建虚拟 numpy 数组略慢。

所以看起来问题出在其他地方。 可能是集群配置错误、从 S3 获取数据的成本,甚至是不切实际的期望。

使用 Spark 时不应使用numpy Spark 有自己的数据处理方法,可确保您有时非常大的文件不会立即加载到内存中,从而超出内存限制。 你应该像这样用 Spark 加载你的文件:

data = sc.textFile("s3_url", initial_num_of_partitions) \
    .map(lambda row: map(lambda x: float(x), row.split(' ')))

现在,这将根据您的示例输出这样的RDD

>>> print(data.collect())
[[1.0, 2.0, 3.0], [5.1, 3.6, 2.1], [3.0, 0.24, 1.333]]

@edit关于文件格式和numpy用法的一些建议:

文本文件与 CSV、TSV、Parquet 或任何您觉得合适的文件一样好。 根据有关二进制文件加载的 Spark 文档,二进制文件不是首选:

binaryFiles ( path , minPartitions=None )

注意:实验

从 HDFS、本地文件系统(在所有节点上可用)或任何 Hadoop 支持的文件系统 URI 作为字节数组读取二进制文件目录。 每个文件被读取为一条记录并以键值对的形式返回,其中键是每个文件的路径,值是每个文件的内容。

注意:小文件是首选,大文件也是允许的,但可能会导致性能不佳。

至于numpy使用,如果我是你,我肯定会尝试用原生 Spark 替换任何外部包,例如pyspark.mlib.random用于随机化: http : pyspark.mlib.random /pyspark.mllib.html#module-pyspark.mllib.random

在这种情况下,最好的做法是使用 pandas 库进行 io。
请参考这个问题: pandas read_csv() and python iterator as input
在那里你会看到如何替换np.loadtxt()函数,这样会更快
创建一个 numpy 数组的 RDD。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM