任务介绍:
对一个100gb对JSON文件进行遍历并处理。同时使用多核并行计算加速,分别使用1 node 1core,1node 8core,2node 4core进行处理测试加速速度。数据处理只是简单的对文件中字典的数值进行加减。处理平台为HPC。
文件介绍:
一个100GB 的json file,内容为推上的评论,本身没有进行过index。所有的rows存在一个rows[ ]list中, 每一行都是一个单独的评论,我们需要对每一个评论进行分析,获取其中一个属性的总和。我介绍的处理方法仅对分行处理过的数据有效。(或者说只要要处理的单元有规律可循也可以用类似的方法)
对于如何确认自己的json是否分行,直接vscode打开json文件看就能看出来。你要是发现打开来它直接就是向我下面的图那样一行行分好的那就是分行过了的。
处理方法:
由于处理内容本身非常简单,所以其实主要的性能消耗来源于对文件遍历产生的I/O. 想要让多核成功加速,唯一的方法就是让多核分别阅读json文件的一部分,把文件遍历这部分任务平均分给8个core从而加速。
用于文件过大,无法就算用hpc内存也吃不消,没法直接load到内存里直接跳转。所以为了让每个核心只遍历文件的一小部分而不是全部,我的处理方法为直接通过seek()读到文件的特定字节点,然后分析对单行进行分析重新定位到新的row。
首先获取file的大小,除以并行核心数获得每个核心要处理的字节数:
然后打开文件,必须使用rb模式打开,通过获取二进制位置而不是字节位置从而避免.tell()无法获取当前位置:
直接用seek()跳转到计算好了的跳转位置,避免了遍历之前的文件内容。然后开启一个循环,这个一行行的阅读这个文件,知道它发现当前位置超过了它需要遍历内容,返回统计后的字典。
由于我的文件事按行数来分割内容,所以可以直接用readline()来找到\n的位置从而进入下一行。这可以保证读取的数据都是一个完整的一行。由于这是一个字典文件,所以每一个{ 字典内容 } row行的最后都有一个‘,’ 所以通过line[:-1]取出他。这样处理后的单行就是一个完整的json文件,可以使用python 的json.load直接分析为一个python字典文件:
处理为python 字典后的处理就很简单了。
这样处理后,文件会一行行的处理这个文件,不会导致分析过大文件导致文件爆内存。同时也能保证每个core只处理1/cores 的文件内容,从而大幅提升处理这个json的处理速度。
在使用这个方法后,处理100gb文件,8核比单核快了7倍。
分配给多核的方法:
使用mpi来进行多核心管理,用于我使用的是python,所以用的是mpi4py库:
最后用SLURM提交任务