关于python:是否可以将多个args传递给multiprocessing.pool?

Is it possible to pass multiple args to multiprocessing.pool?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
Python multiprocessing pool.map for multiple arguments

我想向多处理池中的子进程提供两个参数。我觉得我在上山。它可能是2个参数,或者一个元组,或者…完全?对于某些人来说,它似乎可以正常工作,正确地传递出两个文件名(in和out),但随后会在变量点意外地出错。遗憾的是,它并没有真正起作用,因为输出文件都是空的——如果我直接调用它或单进程调用它,就不会发生这种情况。还有一个复杂的因素,被调用的例程在另一个导入的模块中。将其定位为"foo"存根模块可以解决问题,但它只打印参数,而不尝试执行任何实际工作。

这也许是一个很长的路顽固地抵制学习如何使用一个队列,但我只是想确认我不会得到任何地方推下我的道路。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
fixtures/txt_data/AAD.txt obj/txt_data/AAD.txt
fixtures/txt_data/ANZSMW.txt obj/txt_data/ANZSMW.txt
fixtures/txt_data/BENPA.txt obj/txt_data/BENPA.txt
fixtures/txt_data/CBAIZQ.txt obj/txt_data/CBAIZQ.txt
Traceback (most recent call last):
  File"./jobflow.py", line 60, in <module>
    main()
  File"./jobflow.py", line 57, in main
    args.func(args)
  File"./jobflow.py", line 40, in market
    pool.map(foo, market_files())
  File"/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/pool.py", line 225, in map
  return self.map_async(func, iterable, chunksize).get()
File    "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/pool.py", line 522, in get
raise self._value
TypeError: function takes exactly 1 argument (2 given)
fixtures/txt_data/CSDO.txt obj/txt_data/CSDO.txt
fixtures/txt_data/EMB.txt obj/txt_data/EMB.txt
fixtures/txt_data/GGG.txt obj/txt_data/GGG.txt
fixtures/txt_data/IDL.txt obj/txt_data/IDL.txt

这是一个错误样本。它会在文件用完之前停止。或者它会抱怨它需要2个参数,但只有当我将其更改为尝试传递两个参数时才会得到1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def foo(c):
    a, b, = c
    print a, b
    market2.file_main((a, b))  # does comment/uncommenting this break it only because it's in another python file?

def market(args):
   """
    read raw ticker data files and output nice, clean, more valid ticker data files
   """

    pool = multiprocessing.Pool()

    class market_files(object):
        for infile in args.infiles:
            outfile = os.path.join(args.outdir, os.path.basename(infile))
            yield (infile, outfile)

    pool.map(foo, market_files())


哦,等等,它确实有效,但不是直接传递多个参数,而是将它们放入一个元组中。

我通过在每次迭代中生成一个新的Processp.start()来实现它,这两个迭代生成了大量荒谬的进程;-)但确实吞没了多个参数。

从那里开始,我把iterable简化成一个列表(现在我已经计算出iterable可能很好了),但我认为主要的事情是将args作为元组传递。一定是在切割室地板上弄得一团糟,看不到解决方案的其中之一。

所以在控制器中我有:

1
2
3
4
5
6
7
    arglist = []
    for infile in args.infiles:
        outfile = os.path.join(args.outdir, os.path.basename(infile))
        arglist.append((infile, outfile))

    pool = multiprocessing.Pool()
    p = pool.map(func=market2.process, iterable=arglist)

在模块中:

1
2
3
4
5
6
7
    def process(x):
        infile, outfile = x
        instream = open(infile, 'rB')
        outstream = open(outfile, 'wB')
        main(instream, outstream)
        instream.close()
        outstream.close()

4核性能(分钟):

  • 单螺纹=3:54
  • 使用子进程=4:52(我认为它默认阻塞以便计算)
  • 同时使用Process的Squillions=2:41(饱和所有内核,每个进程1-4%的CPU)
  • 使用池=2:13