Python多处理:如何知道使用池或进程?

2024-03-29 04:47:17 发布

您现在位置:Python中文网/ 问答频道 /正文

所以我有一个我正在编写的算法,函数multiprocess应该调用另一个函数CreateMatrixMp(),在尽可能多的进程上并行地调用cpu。我以前从未做过多处理,无法确定下面哪种方法更有效。在函数CreateMatrixMp()的上下文中使用的“efficient”一词可能需要调用数千次。我已经阅读了python multiprocessing模块的所有文档,并有以下两种可能:

首先是使用Pool类:

def MatrixHelper(self, args):
    return self.CreateMatrix(*args)

def Multiprocess(self, sigmaI, sigmaX):

    cpus = mp.cpu_count()
    print('Number of cpu\'s to process WM: %d' % cpus)
    poolCount = cpus*2
    args = [(sigmaI, sigmaX, i) for i in range(self.numPixels)]

    pool = mp.Pool(processes = poolCount, maxtasksperchild= 2)
    tempData = pool.map(self.MatrixHelper, args)
    pool.close()
    pool.join()

接下来是使用Process类:

def Multiprocess(self, sigmaI, sigmaX):

    cpus = mp.cpu_count()
    print('Number of cpu\'s to process WM: %d' % cpus)

    processes = [mp.Process(target = self.CreateMatrixMp, args = (sigmaI, sigmaX, i,)) for i in range(self.numPixels)]
    for p in processes:
        p.start()
    for p in processes:
        p.join()

Pool似乎是更好的选择。我听说这会减少开销。并且Process不考虑计算机上的CPU数量。唯一的问题是以这种方式使用Pool会给我一个又一个错误,每当我修复一个错误时,它下面就会有一个新的错误。Process似乎更容易实现,而且据我所知,这可能是更好的选择。你的经验告诉你什么?

如果应该使用Pool,那么我选择map()是否正确?最好维持订单。我有tempData = pool.map(...),因为map函数应该返回每个进程的结果列表。我不确定Process如何处理返回的数据。


Tags: 函数inselfmapforargsmpcpu
1条回答
网友
1楼 · 发布于 2024-03-29 04:47:17

我认为Pool类通常更方便,但这取决于您希望结果是有序的还是无序的。

假设要创建4个随机字符串(例如,。可能是一个随机的用户ID生成器,大约是这样的):

import multiprocessing as mp
import random
import string

# Define an output queue
output = mp.Queue()

# define a example function
def rand_string(length, output):
    """ Generates a random string of numbers, lower- and uppercase chars. """
    rand_str = ''.join(random.choice(
                    string.ascii_lowercase
                    + string.ascii_uppercase
                    + string.digits)
               for i in range(length))
    output.put(rand_str)

# Setup a list of processes that we want to run
processes = [mp.Process(target=rand_string, args=(5, output)) for x in range(4)]

# Run processes
for p in processes:
    p.start()

# Exit the completed processes
for p in processes:
    p.join()

# Get process results from the output queue
results = [output.get() for p in processes]

print(results)

# Output
# ['yzQfA', 'PQpqM', 'SHZYV', 'PSNkD']

在这里,顺序可能无关紧要。我不确定是否有更好的方法来实现这一点,但是如果我想按照调用函数的顺序跟踪结果,我通常会返回以ID作为第一项的元组,例如

# define a example function
def rand_string(length, pos, output):
    """ Generates a random string of numbers, lower- and uppercase chars. """
    rand_str = ''.join(random.choice(
                    string.ascii_lowercase
                    + string.ascii_uppercase
                    + string.digits)
                for i in range(length))
    output.put((pos, rand_str))

# Setup a list of processes that we want to run
processes = [mp.Process(target=rand_string, args=(5, x, output)) for x in range(4)]

print(processes)

# Output
# [(1, '5lUya'), (3, 'QQvLr'), (0, 'KAQo6'), (2, 'nj6Q0')]

接下来让我对结果进行排序:

results.sort()
results = [r[1] for r in results]
print(results)

# Output:
# ['KAQo6', '5lUya', 'nj6Q0', 'QQvLr']

泳池班

现在你的问题是:这与Pool类有什么不同? 您通常希望Pool.map返回结果的有序列表,而不必经历创建元组和按I d排序的过程。因此,我认为它通常更有效。

def cube(x):
    return x**3

pool = mp.Pool(processes=4)
results = pool.map(cube, range(1,7))
print(results)

# output:
# [1, 8, 27, 64, 125, 216]

同样,还有一种“应用”方法:

pool = mp.Pool(processes=4)
results = [pool.apply(cube, args=(x,)) for x in range(1,7)]
print(results)

# output:
# [1, 8, 27, 64, 125, 216]

在进程完成之前,Pool.applyPool.map都将锁定主程序。

现在,您还有Pool.apply_asyncPool.map_async,它们在进程完成后立即返回结果,这与上面的Process类基本相似。其优点可能是它们为您提供了方便的applymap功能,您可以从Python的内置applymap中了解这些功能

相关问题 更多 >