Pandas在NFS上读取CSV文件速度非常慢

3

我有一个非常简单的脚本,使用 pandas.parse_csv 方法加载大型数据集。

import pandas as pd
import numpy as np

USE_COLUMNS = [0,1,2,11,13,14]

def parse_csv(filename):
    df = pd.read_csv(filename,
                     header=None,
                     compression='bz2',
                     delim_whitespace=True,
                     dtype={11:np.float32, 13:np.float32, 14:np.float32},
                     skip_blank_lines=True,
                     skiprows=4,
                     parse_dates=[[1,2]],
                     usecols=USE_COLUMNS,
                     error_bad_lines=False,
                     infer_datetime_format=True,
                     iterator=True,
                     chunksize=100000,
                     low_memory=False,
                     engine='c')
    return df

fname = 'test.log.bz2'
iter = parse_csv(fname)
df = pd.concat([chunk[chunk[14] > 60000] for chunk in iter])
print df

文件test.log.bz2压缩后为1.1GB,解压后超过5GB,共有15列,只使用其中的一些。在我的本地机器上,运行该脚本需要约200秒。但在生产环境中,它需要53分钟(16倍减速)!我该怎么解决呢?

在我的本地机器上,我使用的是SATA SSD,而在生产环境中,NFS支持的文件系统是唯一的选择。

我正在使用 pandas 版本 0.16.2。

我在我的本地机器上使用 strace 运行了此脚本,以下是结果:

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 57.09    0.038753           2     15618           mremap
 18.83    0.012780           0    109476           munmap
 14.81    0.010055           0    109669           mmap
  3.44    0.002337           0    259922           read
  2.10    0.001427           0      5549      4780 open
  1.45    0.000987           1       713           brk

strace 在生产环境中的结果:

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 92.41    0.491816          46     10766           mremap
  4.59    0.024412           7      3491      2814 open
  0.76    0.004065           0      9897           read
  0.75    0.003999          15       274       274 unlink
  0.50    0.002652           3       974       838 stat
  0.47    0.002498        1249         2           clone
  0.35    0.001865           0      4659           munmap
------ ----------- ----------- --------- --------- ----------------
100.00    0.532200                 37118      3997 total

好的,把你的生产NFS放到SSD上,使用10GiB以太网,然后你可以比较速度 ;) 现在说正经的 - 我会开始考虑HDFS和Apache Spark处理5GB以上的文件。 - MaxU - stand with Ukraine
复制打包文件到运行Pandas的机器上并在那里解压需要多长时间?我的意思是仅这两个操作,不涉及读取/解析CSV... - MaxU - stand with Ukraine
1
在生产机器上复制和解压缩文件后,解析(read_csv)解压缩文件需要多长时间? - MaxU - stand with Ukraine
你尝试过完整地读取文件吗(而不是分块)?无论如何,之后你将其连接成单个DF,因此可以节省concat()的使用。 - MaxU - stand with Ukraine
根据我的经验,在相同系统上使用相同文件,pandas所需的时间至少是fread(在R中)所需时间的20倍。我们需要比read.csv更好的东西。要好得多。 - Hack-R
显示剩余7条评论
1个回答

0
我建议您在将数据加载到pandas之前使用标准工具(bzip2gawk)对数据进行预过滤:
bzip2 -dc /path/to/test.log.bz2 | gawk -F"," 'NR > 4 && $15 > 600000.0 {print}' > /path/to/test_filtered.log

这样做应该会更快,占用的内存也会少得多。

请注意使用 $15 而不是 chunk[14] - AWK 从1开始计算列数。

之后,您可以将预过滤的未压缩 CSV 文件简单地加载到 pandas 中。

附注:您可能还想要调整您的 NFS。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接