python多处理读取文件花费了太多时间

python多处理读取文件花费了太多时间,python,file-read,Python,File Read,我的代码中有一个函数可以读取文件。每个文件大约8米,但是读取速度太低,为了提高速度,我使用了多重处理。遗憾的是,它似乎被阻塞了。我想知道有什么方法可以帮助解决这个问题并提高读取速度 我的代码如下: import multiprocessing as mp import json import os def gainOneFile(filename): file_from = open(filename) json_str = file_from.read() temp

我的代码中有一个函数可以读取文件。每个文件大约8米,但是读取速度太低,为了提高速度,我使用了多重处理。遗憾的是,它似乎被阻塞了。我想知道有什么方法可以帮助解决这个问题并提高读取速度

我的代码如下:

import multiprocessing as mp
import json
import os

def gainOneFile(filename):

    file_from = open(filename)
    json_str = file_from.read()
    temp = json.loads(json_str)
    print "load:",filename," len ",len(temp)
    file_from.close()
    return temp

def gainSortedArr(path):
    arr = []
    pool = mp.Pool(4)
    for i in xrange(1,40):
        abs_from_filename = os.path.join(path, "outputDict"+str(i))
        result = pool.apply_async(gainOneFile,(abs_from_filename,)) 
        arr.append(result.get())

    pool.close()
    pool.join()                                               
    arr = sorted(arr,key = lambda dic:len(dic))

    return arr
以及调用函数:

whole_arr = gainSortedArr("sortKeyOut/")  

你有一些问题。首先,您没有并行化。你可以:

result = pool.apply_async(gainOneFile,(abs_from_filename,)) 
arr.append(result.get())
一次又一次地分派任务,然后立即调用
.get()
,等待任务完成,然后再分派任何其他任务;实际上,您从未同时运行多个工人。存储所有结果而不调用
.get()
,然后稍后调用
.get()
。或者只需使用
Pool.map
或相关方法,并节省手动个人结果管理的一些麻烦,例如(使用
imap\u unordered
将开销降至最低,因为您只是在排序):

其次,
多处理
必须对主进程和工作进程之间发送的所有参数和返回值进行pickle和unpickle处理,这些参数和返回值都通过管道发送,从而导致系统调用开销。由于您的文件系统不太可能从并行读取中获得实质性的速度,因此这可能是一个净损失,而不是收益

通过切换到基于线程的池,您可能会得到一些提升;将
import
更改为
import multiprocessing.dummy为mp
,您将获得一个版本的
Pool
以线程的形式实现;它们不围绕CPython GIL工作,但由于该代码几乎肯定是I/O绑定的,这几乎不重要,而且它消除了酸洗和取消酸洗以及工人通信中涉及的IPC


最后,如果您在类UNIX系统上使用Python3.3或更高版本,则可以让操作系统更积极地将文件拉入系统缓存,从而帮助您解决问题。如果可以打开文件,则在文件描述符上使用(
.fileno()
在文件对象上)无论是使用
WILLNEED
还是
SEQUENTIAL
,当您稍后从文件中读取数据时,都可以通过在请求之前主动预取文件数据来提高读取性能。

问题似乎在于主进程中数据收集期间的序列化/反序列化。通过正在跳过中间字符串
temp=json.load(file\u from)
。这里没有mp的好处。您可以在子进程中解码JSON,但返回父进程时必须再次对其进行序列化和反序列化。它可能比在一个文件中完成所有操作都要慢。在这里,低并行计算的传输成本很高。多处理
Value
Array
使用共享内存。。。这可能有一些好处。但是你可能想尝试其他更快的(?)json解析器。但是我必须读取文件并对其进行解码。有什么解决方案吗@tdelaney@IgnacioVazquez-艾布拉姆斯:在很多情况下,我也会,但那是一整罐我还不想打开的虫子。这也不总是最好的方法;32位系统在处理大文件时会遇到问题,在Python 3上解析JSON文件时,
mmap
对象只能用作
bytes
类对象,而不是
str
,Python 3上的
JSON
只能从
str
加载;您仍然需要从
mmap
中读取和解码,因此您从中获得的收益微乎其微。即使在Py2上,如果
mmap
加载一起工作,我怀疑它最终也会被解码,因此,没有真正的节省。不要忘记,除非您从多个磁盘读取,否则这将是IO绑定的,因此从同一个磁盘读取多个文件,特别是在磁盘旋转时,很可能会影响性能。@Davidermann:对于有限的并行性,它可能会有所帮助(解析一个工作线程中读取的数据所花费的时间就是其他工作线程读取的时间),如果操作系统能够很好地安排读取,它可以减少延迟(当然,如果它在物理磁盘的任一端交错读取数据,也可以很容易地增加延迟)。条带化或镜像RAID阵列或NFS(网络延迟是杀手)也可以使这种模式变得有意义。我确实提到并行读取不太可能产生收益,但这并不意味着它不能。
# Make generator of paths to load
paths = (os.path.join(path, "outputDict"+str(i)) for i in xrange(1, 40))
# Load them all in parallel, and sort the results by length (lambda is redundant)
arr = sorted(pool.imap_unordered(gainOneFile, paths), key=len)