在Jupyter Windows上,使用池并行读取多个文件将永远花费:

时间:2018-11-20 14:00:31

标签: python windows pandas jupyter-notebook python-multiprocessing

我想读取22个文件(存储在我的硬盘上),每个文件有300,000行,以存储在单个pandas数据帧中。我的代码能够在15-25分钟内完成操作。我最初的想法是:我应该使用更多的CPU来使其更快。 (请纠正我,如果我在这里错了,并且如果所有CPU无法同时从同一硬盘读取数据,那么在这种情况下,我们可以假设以后数据可能存在于不同的硬盘中,因此此练习仍然有用)。

我发现很少有类似thisthis的帖子,并尝试了以下代码。

import os
import pandas as pd
from multiprocessing import Pool

def read_psv(filename):
    'reads one row of a file (pipe delimited) to a pandas dataframe'
    return pd.read_csv(filename,
                       delimiter='|',
                       skiprows=1, #need this as first row is junk
                       nrows=1, #Just one row for faster testing                    
                       encoding = "ISO-8859-1", #need this as well                       
                       low_memory=False
                      )



files = os.listdir('.') #getting all files, will use glob later
df1 = pd.concat((read_psv(f) for f in files[0:6]), ignore_index=True, axis=0, sort=False) #takes less than 1 second

pool = Pool(processes=3)
df_list = pool.map(read_psv, files[0:6]) #takes forever
#df2 =  pd.concat(df_list, ignore_index=True) #cant reach this 

这将永远花费(超过30-60分钟,而我杀死进程时还没有完成)。我也经历了similar question like mine,但没有用。

编辑:我正在Windows上使用Jupyter。

2 个答案:

答案 0 :(得分:1)

您的任务是IO受限的,瓶颈是硬盘驱动器。 CPU只需要做一点工作就可以解析CSV中的每一行。

磁盘读取是连续的,最快。如果要读取大文件,最好让磁盘寻找开始,然后依次读取所有字节。

如果同一硬盘驱动器上有多个大文件,并使用多个进程从它们中读取文件,则磁盘头将不得不在它们之间来回跳转,每次跳转最多需要10毫秒。

多处理仍然可以使您的代码更快,但是您需要将文件存储在多个磁盘上,因此每个磁盘头都可以专注于读取一个文件。

另一种选择是购买SSD。磁盘寻道时间要低得多,仅为0.1毫秒,吞吐量要快5倍左右。

答案 1 :(得分:0)

因此,该问题与性能不佳或卡在I / O无关。该问题与Jupyter和Windows有关。在Windows上,我们需要在初始化Pool之前包含以下if子句:if __name__ = '__main__':。对于Jupyter,我们需要将worker保存在单独的文件中,并将其导入代码中。 Jupyter也有问题,因为默认情况下它不提供错误日志。当我在python shell上运行代码时,我才知道Windows问题。在Ipython Shell上运行代码时,我了解到Jupyter错误。后续帖子对我有很大帮助。

For Jupyter

For Windows Issue