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

时间:2015-12-18 04:39:11

标签: python file-read

我的代码中有一个函数应该读取文件。每个文件大约是8M,但读取速度太低,为了改善我使用multiprocessing.sadly,它似乎被阻止了。我想知道有什么方法可以帮助解决这个问题并提高阅读速度吗?

我的代码如下:

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/")  

1 个答案:

答案 0 :(得分:4)

你有一些问题。首先,你没有并行化。你这样做:

result = pool.apply_async(gainOneFile,(abs_from_filename,)) 
arr.append(result.get())

一遍又一遍地调度任务,然后立即调用.get()等待它完成任务,然后再发送任何其他任务;你实际上从未有过一个以上的工人。存储所有结果而不调用.get(),然后再调用.get()。或者只使用Pool.map或相关方法,并从手动个人结果管理中省去一些麻烦,例如: (使用imap_unordered来最小化开销,因为您只是进行排序):

# 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)

其次,multiprocessing必须pickle和unpickle所有参数并返回主进程和worker之间发送的值,并且所有这些都是通过管道发送的,这会引起系统调用开销。由于您的文件系统不太可能通过并行读取获得大幅度的速度,因此可能是净损失,而不是增益。

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

最后,如果您在类似UNIX的系统上使用Python 3.3或更高版本,您可以通过让文件更积极地将文件拉入系统缓存来帮助您。如果您可以打开该文件,则使用文件描述符.fileno()对文件对象WILLNEED使用SEQUENTIAL$linkData = [ // 'link' => 'http://www.example.com', 'message' => 'User provided message', 'source' => $fb->fileToUpload('/img/about_two.jpg'), ]; try { // Returns a `Facebook\FacebookResponse` object $response = $fb->post('/me/photos', $linkData, 'XXXXXXXXXXX'); } catch(Facebook\Exceptions\FacebookResponseException $e) { echo 'Graph returned an error: ' . $e->getMessage(); exit; } catch(Facebook\Exceptions\FacebookSDKException $e) { echo 'Facebook SDK returned an error: ' . $e->getMessage(); exit; } <h1 class="h1name" style="" ><bold><%= @user %></bold><span class="glyphicon glyphicon-pencil" aria-hidden="true"></span></h1> 可能通过在请求之前积极预取文件数据,在稍后读取文件时提高读取性能。