Python多处理-跟踪pool.map操作的进程

Python多处理-跟踪pool.map操作的进程,python,multiprocessing,pool,Python,Multiprocessing,Pool,我有一个函数,它执行一些模拟和 返回字符串格式的数组 我想为您运行模拟(函数) 不同的输入参数值,超过10000个可能的输入值, 并将结果写入单个文件 我使用的是多处理,特别是pool.map函数 并行运行模拟 因为整个过程运行模拟功能超过10000次 花了很长时间,我真的很想跟踪整个操作过程 我认为下面代码中的问题是,pool.map运行函数10000次,在这些操作期间没有任何进程跟踪。一旦并行处理完成运行10000个模拟(可能是数小时到数天),我将继续跟踪10000个模拟结果何时保存到文件中

我有一个函数,它执行一些模拟和 返回字符串格式的数组

我想为您运行模拟(函数) 不同的输入参数值,超过10000个可能的输入值, 并将结果写入单个文件

我使用的是多处理,特别是pool.map函数 并行运行模拟

因为整个过程运行模拟功能超过10000次 花了很长时间,我真的很想跟踪整个操作过程

我认为下面代码中的问题是,pool.map运行函数10000次,在这些操作期间没有任何进程跟踪。一旦并行处理完成运行10000个模拟(可能是数小时到数天),我将继续跟踪10000个模拟结果何时保存到文件中。因此,这并不是真正跟踪pool.map操作的处理

我的代码是否有一个简单的修复程序,允许进程跟踪

def simFunction(input):
    # Does some simulation and outputs simResult
    return str(simResult)

# Parallel processing

inputs = np.arange(0,10000,1)

if __name__ == "__main__":
    numCores = multiprocessing.cpu_count()
    pool = multiprocessing.Pool(processes = numCores)
    t = pool.map(simFunction, inputs) 
    with open('results.txt','w') as out:
        print("Starting to simulate " + str(len(inputs)) + " input values...")
        counter = 0
        for i in t:
            out.write(i + '\n')
            counter = counter + 1
            if counter%100==0:
                print(str(counter) + " of " + str(len(inputs)) + " input values simulated")
    print('Finished!!!!')
没有“简单的解决办法”<代码>映射就是对您隐藏实现细节。在这种情况下,您需要详细信息。也就是说,根据定义,事情变得更加复杂。你需要改变沟通模式。有很多方法可以做到这一点

一种是:创建一个用于收集结果的队列,并让工作人员将结果放入该队列。然后,您可以从监视线程或进程中查看队列,并在结果进入时使用它们。在消费时,您可以分析它们,并生成日志输出。这可能是跟踪进度最常用的方法:您可以以任何方式实时响应传入的结果


更简单的方法可能是稍微修改worker函数,并在其中生成日志输出。通过使用外部工具(如
grep
wc
)仔细分析日志输出,您可以想出非常简单的跟踪方法。

如果您使用迭代的
map
函数,跟踪进度非常容易

>>> from pathos.multiprocessing import ProcessingPool as Pool
>>> def simFunction(x,y):
...   import time
...   time.sleep(2)
...   return x**2 + y
... 
>>> x,y = range(100),range(-100,100,2)
>>> res = Pool().imap(simFunction, x,y)
>>> with open('results.txt', 'w') as out:
...   for i in x:
...     out.write("%s\n" % res.next())
...     if i%10 is 0:
...       print "%s of %s simulated" % (i, len(x))
... 
0 of 100 simulated
10 of 100 simulated
20 of 100 simulated
30 of 100 simulated
40 of 100 simulated
50 of 100 simulated
60 of 100 simulated
70 of 100 simulated
80 of 100 simulated
90 of 100 simulated
或者,您可以使用异步
映射
。在这里,我会做一些不同的事情,只是把它混合起来

>>> import time
>>> res = Pool().amap(simFunction, x,y)
>>> while not res.ready():
...   print "waiting..."
...   time.sleep(5)
... 
waiting...
waiting...
waiting...
waiting...
>>> res.get()
[-100, -97, -92, -85, -76, -65, -52, -37, -20, -1, 20, 43, 68, 95, 124, 155, 188, 223, 260, 299, 340, 383, 428, 475, 524, 575, 628, 683, 740, 799, 860, 923, 988, 1055, 1124, 1195, 1268, 1343, 1420, 1499, 1580, 1663, 1748, 1835, 1924, 2015, 2108, 2203, 2300, 2399, 2500, 2603, 2708, 2815, 2924, 3035, 3148, 3263, 3380, 3499, 3620, 3743, 3868, 3995, 4124, 4255, 4388, 4523, 4660, 4799, 4940, 5083, 5228, 5375, 5524, 5675, 5828, 5983, 6140, 6299, 6460, 6623, 6788, 6955, 7124, 7295, 7468, 7643, 7820, 7999, 8180, 8363, 8548, 8735, 8924, 9115, 9308, 9503, 9700, 9899]
请注意,我使用的是
pathos.multiprocessing
而不是
multiprocessing
。它只是
多处理
的一个分支,使您能够使用多个输入执行
映射
函数,具有更好的序列化功能,并允许您在任何地方执行
映射
调用(而不仅仅是在
\uuuuuu main\uuuuu
)。您也可以使用
多处理
来执行上述操作,但是代码会略有不同

迭代的或异步的
map
将使您能够编写想要更好地跟踪流程的任何代码。例如,给每个作业传递一个唯一的“id”,并观察哪个返回,或者让每个作业返回它的流程id。有很多方法可以跟踪进度和流程……但是上面的内容应该给你一个开始


您可以在这里获得
pathos

我想您需要的是一个日志文件

我建议您使用日志模块,它是Python标准库的一部分。但不幸的是,日志记录不是多处理安全的。所以你不能在你的应用程序中使用它

因此,您需要使用多处理安全日志处理程序,或者使用队列或锁以及日志模块来实现您的日志处理程序

Stackoverflow中对此有很多讨论。例如:

如果大部分CPU负载在模拟功能中,并且您不打算使用日志旋转,那么您可能可以使用如下简单的锁定机制:

import multiprocessing
import logging

from random import random
import time


logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s %(process)s %(levelname)s %(message)s',
    filename='results.log',
    filemode='a'
)


def simulation(a):
    # logging
    with multiprocessing.Lock():
        logging.debug("Simulating with %s" % a)

    # simulation
    time.sleep(random())
    result = a*2

    # logging
    with multiprocessing.Lock():
        logging.debug("Finished simulation with %s. Result is %s" % (a, result))

    return result

if __name__ == '__main__':

    logging.debug("Starting the simulation")
    inputs = [x for x in xrange(100)]
    num_cores = multiprocessing.cpu_count()
    print "num_cores: %d" % num_cores
    pool = multiprocessing.Pool(processes=num_cores)
    t = pool.map(simulation, inputs)
    logging.debug("The simulation has ended")
您可以在运行时“tail-f”日志文件。这是您应该看到的:

2015-02-08 18:10:00,616 3957 DEBUG Starting the simulation
2015-02-08 18:10:00,819 3961 DEBUG Simulating with 12
2015-02-08 18:10:00,861 3965 DEBUG Simulating with 28
2015-02-08 18:10:00,843 3960 DEBUG Simulating with 20
2015-02-08 18:10:00,832 3959 DEBUG Simulating with 16
2015-02-08 18:10:00,812 3958 DEBUG Simulating with 8
2015-02-08 18:10:00,798 3963 DEBUG Simulating with 4
2015-02-08 18:10:00,855 3964 DEBUG Simulating with 24
2015-02-08 18:10:00,781 3962 DEBUG Simulating with 0
2015-02-08 18:10:00,981 3961 DEBUG Finished simulation with 12. Result is 24
2015-02-08 18:10:00,981 3961 DEBUG Simulating with 13
2015-02-08 18:10:00,991 3958 DEBUG Finished simulation with 8. Result is 16
2015-02-08 18:10:00,991 3958 DEBUG Simulating with 9
2015-02-08 18:10:01,130 3964 DEBUG Finished simulation with 24. Result is 48
2015-02-08 18:10:01,131 3964 DEBUG Simulating with 25
2015-02-08 18:10:01,134 3964 DEBUG Finished simulation with 25. Result is 50
2015-02-08 18:10:01,134 3964 DEBUG Simulating with 26
2015-02-08 18:10:01,315 3961 DEBUG Finished simulation with 13. Result is 26
2015-02-08 18:10:01,316 3961 DEBUG Simulating with 14
2015-02-08 18:10:01,391 3961 DEBUG Finished simulation with 14. Result is 28
2015-02-08 18:10:01,391 3961 DEBUG Simulating with 15
2015-02-08 18:10:01,392 3963 DEBUG Finished simulation with 4. Result is 8
2015-02-08 18:10:01,393 3963 DEBUG Simulating with 5
在Windows和Linux上尝试过


希望这有帮助

谢谢。您能提供一些简单的示例吗?
多处理。get_logger()
返回受锁保护的功能受限的记录器,请参见“是”,但这是模块记录器。。。因此,尽管你可以使用它,你的日志将与模块级消息混合在一起:尝试一下,你会看到这样的消息:2015-02-08 23:47:10954 9288调试创建了带句柄的semlock 448哦,你说得对,我实际上从未使用过它,而且浏览文档的速度太快。