【问题标题】:python multiprocessing slower than normal - calculation too trivial?python多处理比正常慢 - 计算太琐碎?
【发布时间】:2015-08-03 18:44:30
【问题描述】:

我对 python 中的并行处理没有太多经验。 我有一个脚本,它接收几个 fit 文件,这些文件基本上是图像,将它们读入 3D numpy 数组并对其进行一些计算。 我猜“最糟糕”的部分是,我有 2 个 for 循环,遍历数组的两个维度。在循环内部,我基本上得到一个列表,其中包含给定 x 和 y 坐标处的 numpy 数组的第三维。然后我计算最大值,以及最大值所在的索引。然后我将结果写入两个新的二维数组中,它们的 x 和 y 坐标相同。

对于尺寸约为 6000x6000x20 的 fit 文件,这可能需要几分钟才能完成。 然后我尝试让这个并行运行,因为每个 2D 视线都是相互独立的,因此可以在单独的过程中计算。

我查看了一些调用多处理的基本教程,但每次我尝试它,它需要 10 倍的时间...... 我在这里读过一些问题,多处理可能会产生很多开销。是否有可能开销所需的处理时间比过程中的实际计算要长很多,这就是它慢得多的原因?

谢谢。

这是我整理的一个示例脚本。

import numpy,time
import multiprocessing as mp

xs = 500
data = numpy.random.rand(100,xs,xs)
data2 = numpy.zeros(shape=(xs,xs))

def calculation(los):
    maxindex = numpy.argmax(los)
    return maxindex

t0 = time.time()
for x in range(xs):
    for y in range(xs):
        los = data[:,x,y]
        data2[x,y]=calculation(los)
t1 = time.time()
print t1-t0

t0 = time.time()
pool = mp.Pool(processes=4)
results = [pool.apply_async(calculation, args=(data[:,x,y],)) for x in range(xs) for y in range(xs)]
t1 = time.time()

print t1-t0

第一个版本大约需要 1 秒,第二个版本 12 在我的机器上需要几秒钟。

【问题讨论】:

  • 多处理不是灵丹妙药。能否附上相关代码?
  • 您应该批量处理数据并将其发送到工作进程。使用多处理,额外的成本在于进程之间的数据传递。由于在这里您决定有 4 个进程,因此您可以将数据分成 4 个并发送块,从而最大限度地降低传输成本。
  • 我不能让所有进程处理相同的数据吗?
  • 池所做的是创建一个作业列表,每个作业包含一行数据,将传递给您创建的 4 个进程之一。发送消息需要时间,发送 500*500 条消息需要更多时间。这就是为什么它非常慢。您可以做的最好的事情是减少要发送的消息数量,例如只发送 4 个,因为您有 4 个进程。
  • 答案对您有用吗?如果可以,你能接受吗?

标签: python arrays numpy multiprocessing fits


【解决方案1】:

您可以发送批量数据,因为消息传递是昂贵的部分:

import numpy,time
import multiprocessing as mp

xs = 500
data = numpy.random.rand(100,xs,xs)
data2 = numpy.zeros(shape=(xs,xs))

def calculation(los):
    maxindex = numpy.argmax(los)
    return maxindex

def calculation_batch(los):
    maxindex = []
    for l in los:
        maxindex.append(umpy.argmax(los))
    return maxindex


t0 = time.time()
for x in range(xs):
    for y in range(xs):
        los = data[:,x,y]
        data2[x,y]=calculation(los)
t1 = time.time()
print t1-t0

t0 = time.time()
pool = mp.Pool(processes=4)
results = [pool.apply_async(calculation, args=(data[:,x:x+250,y:y+250],)) for x in [0, 250] for y in [0, 250]]
t1 = time.time()

print t1-t0

这给了我:

0.787902832031
0.846422195435

【讨论】:

    猜你喜欢
    • 2016-02-14
    • 2014-11-16
    • 1970-01-01
    • 1970-01-01
    • 2014-11-12
    • 1970-01-01
    • 1970-01-01
    • 2016-11-08
    • 2015-01-12
    相关资源
    最近更新 更多