多处理如此缓慢

时间:2019-01-05 08:51:35

标签: python pandas parallel-processing multiprocessing python-multiprocessing

我有一个执行以下操作的函数:

  • 将文件作为输入并进行基本清理。
  • 从文件中提取所需的项目,然后将其写入pandas数据框中。
  • 数据帧最终被转换为csv并写入文件夹。

这是示例代码:

def extract_function(filename):  
   with open(filename,'r') as f:  
       input_data=f.readlines()  
   try:
     // some basic searching pattern matching extracting  
     // dataframe creation with 10 columns and then extracted values are filled in
        empty dataframe
     // finally df.to_csv()

if __name__ == '__main__':
   pool_size = multiprocessing.cpu_count()
   filenames=os.listdir("/home/Desktop/input")
   pool=multiprocessing.Pool(pool_size)
   pool.map(extract_function,filenames)
   pool.close()
   pool.join()

input 文件夹中的文件总数为4000。我使用了多重处理,因为使用 for循环正常运行程序会花费一些时间。下面是两种方法的执行时间:

  

正常CPU处理= 139.22秒
  多处理= 18.72秒

我的系统规格为:

  

英特尔i5第7代,12GB内存,1TB硬盘,Ubuntu 16.04

在运行包含4000个文件的程序时,所有内核都已得到充分使用(每个内核平均占90%)。因此,我决定增加文件大小并重复该过程。这次输入文件号从4000增加到1,20,000。但是这一次在运行代码时,cpu的使用在开始时不稳定,一段时间后利用率下降了(平均每个内核的利用率约为10%)。内存利用率也很低,平均最大值为4gb(剩余8gb)。输入4000个文件后,立即写入csv的文件很快,因为我可以立即看到一个跳跃或大约1000个文件或更多。但是当输入120,000个文件时,文件写入速度减慢到300个文件左右,并且这种减慢速度呈线性关系,一段时间后,文件写入速度一下子变为50-70。一直以来,大多数公羊都是免费的。我重新启动了计算机,并尝试使用相同的方法清除任何不需要的僵尸进程,但结果仍然相同。

这是什么原因? 如何对大型文件实现相同的多处理?

注意:
*每个文件大小平均约为300kb。
*正在写入的每个输出文件约为200字节。
*文件总数为4080。因此,总大小约为1.2gb。
*相同的4080个文件被用于复制以获得1,20,000个文件。
*该程序是用于检查大量文件的多重处理的实验。

更新1

我在功能更强大的计算机上尝试了相同的代码。

  

Intel i7 8th gen 8700、1Tb SSHD和60GB内存。

。文件写入比普通HDD快得多。该程序采用了:

  • 对于4000个文件-3.7秒
  • 对于1,20,000个文件-2分钟

在实验中的某个时间点,我获得了最快的完成时间,为84秒。当时,连续两次尝试给了我一致的结果。认为可能是因为我已正确设置了池大小中的线程因子数,所以我重新启动并再次尝试。但这一次要慢得多。为了提供一个角度,在正常运行期间,一秒钟或两秒钟左右将写入3000-4000个文件,但是这次它在一秒钟内写入600个以下的文件。在这种情况下,也完全不使用撞锤。 即使使用了多处理模块,CPU的平均利用率也只有3-7%。

2 个答案:

答案 0 :(得分:2)

与从RAM中运行代码和数据相比,读写磁盘的速度很慢。与运行CPU中内部缓存中的代码和数据相比,它极其慢。

为了加快速度,使用了多个缓存。

  1. 硬盘通常具有内置缓存。在2012年,我对此进行了一些书面测试。禁用硬盘的写缓存后,写入速度从72 MiB / s降至12 MiB / s。
  2. 当今大多数操作系统都使用其他情况下未占用的RAM作为磁盘缓存。
  3. CPU也具有多个内置缓存级别。

(通常,有一种方法可以禁用高速缓存1和2。如果尝试这样做,则会发现读写速度像石头一样下降。)

所以我的猜测是,一旦传递了一定数量的文件,就会耗尽一个或多个缓存,而磁盘I / O成为瓶颈。

要进行验证,您必须将代码添加到tail -n300 /var/solr/logs/solr.log 中以测量3件事:

  • 从磁盘读取数据需要多长时间。
  • 计算需要多长时间。
  • 编写CSV需要多长时间。

extract_function返回这三个数字的元组,并对其进行分析。我建议不要使用extract_function来代替map,这样您就可以在数字可用时立即开始评估。

如果磁盘I / O确实是问题所在,请考虑使用SSD。

答案 1 :(得分:0)

按照ConcurrentModificationException@RolandSmith的建议,我通过用数据帧替换并附加到IO来避免IO连续写入CSV文件。我认为这消除了不一致之处。我按照@selbie的建议检查了“羽毛” “ paraquet” 高性能IO模块,但我认为这是用于将大文件压缩为较小的数据帧结构体。附加选项不存在。

观察:

  • 程序在第一次运行时运行缓慢连续运行会更快。这种行为是一致的。
  • 我已经检查了程序完成后是否正在运行一些尾随的python进程,但找不到任何进程。因此,CPU / RAM内有某种类型的缓存,可以使程序连续运行的速度更快。
  

用于 4000个输入文件的程序花费 72秒进行首次执行,然后平均花费 14-15秒之后的所有成功运行

  • 重新启动系统会清除这些缓存,并使程序在第一次运行时运行速度变慢。

  • 平均新运行时间为72秒。但是,在程序启动后立即将其杀死,然后运行,终止后的第一次空运行需要 40秒。所有连续运行后平均需要14秒。

  • 新运行期间,所有核心利用率约为 10-13%。但是,在所有成功运行之后,利用率的核心将是 100%

经检查有1,20,000个文件,它遵循相同的模式。因此,目前,已解决了不一致问题。因此,如果需要将此类代码用作服务器,则应先进行试运行以使CPU / RAM得以缓存,然后才能开始接受API查询以获得更快的结果。