在Python中使用多处理高效地创建1%的示例

在Python中使用多处理高效地创建1%的示例,python,multiprocessing,Python,Multiprocessing,我正在尝试使用多处理逐行处理大型数据集(300GB)。我想定义一个基于一个变量的1%随机样本。我的第一步是定义示例,然后我想使用多处理读取数据文件。我猜想,如果我定义用于随机样本的集合的部分没有为每个子对象运行,脚本将运行得更快。但是,当我尝试将脚本的这一部分移动到if\uuuuu name\uuuuuu==“\uuuuu main\uuuuu”行下时:子程序似乎不再识别来自父程序的随机样本。我得到一个错误: NameError:未定义名称“id\u pct1” 将脚本中我定义随机样本的部分放在

我正在尝试使用多处理逐行处理大型数据集(300GB)。我想定义一个基于一个变量的1%随机样本。我的第一步是定义示例,然后我想使用多处理读取数据文件。我猜想,如果我定义用于随机样本的集合的部分没有为每个子对象运行,脚本将运行得更快。但是,当我尝试将脚本的这一部分移动到
if\uuuuu name\uuuuuu==“\uuuuu main\uuuuu”行下时:
子程序似乎不再识别来自父程序的随机样本。我得到一个错误:

NameError:未定义名称“id\u pct1”

将脚本中我定义随机样本的部分放在哪里最有效

#define sample
uid = list(line.strip() for line in open('Subsets/unique_ids_final.txt'))
pct1 = round(len(uid)/100)
random.seed(1)
id_pct1 = set(random.sample(uid, k=pct1))
id_pct1.add(vname)

#read original file and write 1% sample using multiprocessing
def worker(chunkStart, chunkSize, q):
    with open('myfile.txt') as f:
        tlines = []
        f.seek(chunkStart)
        lines = f.read(chunkSize).splitlines()
        for line in lines:
            data = line.split('*')
            if data[30] in id_pct1: tlines.append(line)
        q.put(tlines)
        return tlines

def chunkify(fname,size=1024*1024):
    fileEnd = os.path.getsize(fname)
    with open(fname, 'r') as f:
        chunkEnd2 = 0
        while True:
            chunkStart = chunkEnd2
            f.seek(chunkStart)
            f.read(size)
            chunkEnd1 = f.tell()
            f.readline()
            chunkEnd2 = f.tell()
            chunkSz = 1024*1024 + chunkEnd2 - chunkEnd1 - 1
            yield chunkStart, chunkSz
            if chunkEnd2 >= fileEnd:
                break

def listener(q):
    with open('myfile1pct.txt', 'w') as out_f1:
        while True:
            m = q.get()
            if m == 'kill': break
            else:
                for line in m:
                    out_f1.write(line+'\n')
                    out_f1.flush()

def main():

    manager = mp.Manager()
    q = manager.Queue()
    pool = mp.Pool()

    watcher = pool.apply_async(listener, (q,))

    jobs = []
    for chunkStart, chunkSize in chunkify('myfile.txt'):
        jobs.append(pool.apply_async(worker,(chunkStart,chunkSize,q)))

    for job in jobs:
        job.get()

    q.put('kill')
    pool.close()
    pool.join()

if __name__ == '__main__':
    main()

如果您希望
#define
中的这些项目在整个程序中都可用,则应在其前面使用关键字。然而,声明全局变量通常被认为是不好的做法。你应该考虑在你的函数中加入你的<代码>定义> <代码>逻辑,比如::

 #read original file and write 1% sample using multiprocessing
def worker(chunkStart, chunkSize, q):
    #define sample
    uid = list(line.strip() for line in open('Subsets/unique_ids_final.txt'))
    pct1 = round(len(uid)/100)
    random.seed(1)
    id_pct1 = set(random.sample(uid, k=pct1))
    id_pct1.add(vname)

    with open('myfile.txt') as f:
        tlines = []
        f.seek(chunkStart)
        lines = f.read(chunkSize).splitlines()
        for line in lines:
            data = line.split('*')
            if data[30] in id_pct1: tlines.append(line)
        q.put(tlines)
        return tlines

def chunkify(fname,size=1024*1024):
    fileEnd = os.path.getsize(fname)
    with open(fname, 'r') as f:
        chunkEnd2 = 0
        while True:
            chunkStart = chunkEnd2
            f.seek(chunkStart)
            f.read(size)
            chunkEnd1 = f.tell()
            f.readline()
            chunkEnd2 = f.tell()
            chunkSz = 1024*1024 + chunkEnd2 - chunkEnd1 - 1
            yield chunkStart, chunkSz
            if chunkEnd2 >= fileEnd:
                break

def listener(q):
    with open('myfile1pct.txt', 'w') as out_f1:
        while True:
            m = q.get()
            if m == 'kill': break
            else:
                for line in m:
                    out_f1.write(line+'\n')
                    out_f1.flush()

def main():

    manager = mp.Manager()
    q = manager.Queue()
    pool = mp.Pool()

    watcher = pool.apply_async(listener, (q,))

    jobs = []
    for chunkStart, chunkSize in chunkify('myfile.txt'):
        jobs.append(pool.apply_async(worker,(chunkStart,chunkSize,q)))

    for job in jobs:
        job.get()

    q.put('kill')
    pool.close()
    pool.join()

if __name__ == '__main__':
    main()

如果希望
#define
中的这些项目在整个程序中都可用,则应使用关键字
global
然而,声明全局变量实际上是一个很糟糕的做法。你应该考虑在函数中加入你的<代码>定义> <代码>逻辑。我确认这实际上会减慢事情的速度。我猜这是因为样本定义,(需要一段时间运行)。,将为每个块重新运行。这实际上会增加示例的定义次数,从而降低速度。全局是唯一的解决方案吗?你是对的--我的解决方案可能会降低速度,但它修复了你在问题中遇到的问题。如果解决方案回答了你的问题,则应将其标记为“已接受”如果你想优化我的答案,我建议你去codereview[,他们是那边优化方面的专家:)这很公平。它确实修复了错误。如果其他人对如何更有效地执行此操作有想法,请让我知道。如果你想查看代码,真的,在codereview上发布。这就是该网站的目的。如果你查看我的帐户,我已经在那里发布了几次,并获得了令人惊讶的反馈。不是吗o加快速度,我尝试使用全局解决方案,但仍然出现相同的错误。我将如何实现这一点?