【问题标题】:Parallelizing through Multi-threading and Multi-processing taking significantly more time than serial通过多线程和多处理进行并行化比串行花费更多的时间
【发布时间】:2017-12-08 20:14:02
【问题描述】:

我正在尝试学习如何在 python 中进行并行编程。我写了一个简单的 int square 函数,然后串行、多线程、多进程运行:

import time
import multiprocessing, threading
import random


def calc_square(numbers):
    sq = 0
    for n in numbers:
        sq = n*n

def splita(list, n):
    a = [[] for i in range(n)]
    counter = 0
    for i in range(0,len(list)):
        a[counter].append(list[i])
        if len(a[counter]) == len(list)/n:
            counter = counter +1
            continue
    return a


if __name__ == "__main__":

    random.seed(1)
    arr = [random.randint(1, 11) for i in xrange(1000000)]
    print "init completed"

    start_time2 = time.time()
    calc_square(arr)
    end_time2 = time.time()

    print "serial: " + str(end_time2 - start_time2)

    newarr = splita(arr,8)
    print 'split complete'

    start_time = time.time()

    for i in range(8):
        t1 = threading.Thread(target=calc_square, args=(newarr[i],))

        t1.start()
        t1.join()

    end_time = time.time()

    print "mt: " + str(end_time - start_time)

    start_time = time.time()

    for i in range(8):
        p1 = multiprocessing.Process(target=calc_square, args=(newarr[i],))
        p1.start()
        p1.join()

    end_time = time.time()

    print "mp: " + str(end_time - start_time)

输出:

init completed
serial: 0.0640001296997
split complete
mt: 0.0599999427795
mp: 2.97099995613

但是,如您所见,发生了一些奇怪的事情,mt 与 serial 花费的时间相同,而 mp 实际上花费的时间要长得多(几乎长 50 倍)。

我做错了什么?有人可以将我推向正确的方向来学习 Python 中的并行编程吗?

编辑 01

查看 cmets,我发现可能不返回任何内容的函数似乎毫无意义。我什至尝试这样做的原因是因为之前我尝试了以下添加功能:

def addi(numbers):
    sq = 0
    for n in numbers:
        sq = sq + n
    return sq

我尝试将每个部分的加法返回到序列号加法器,因此至少我可以看到与纯序列实现相比有一些性能改进。但是,我不知道如何存储和使用返回的值,这就是我试图找出比这更简单的东西的原因,它只是划分数组并在其上运行一个简单的函数。

谢谢!

【问题讨论】:

  • 你创建线程,启动它,然后等待它完成它的工作。为什么这应该比在主线程中执行相同的工作更快?是的,创建线程并不是一个快速的操作。
  • 你重复你的multiprocessing计算8次。加上产生一个进程的开销。要么预先分配工作并传递给每个进程一个块,要么使用pool。由于 GIL,线程不会加速 CPU 密集型任务。
  • 那么我应该如何并行运行线程呢?
  • 我已经对此进行了试验,得到了相同的结果,即使在允许创建所有 Processes
  • @roganjosh 我在数组的 8 个不同部分运行了相同的函数。如何使用池或为每个进程传递一个块?

标签: python multithreading parallel-processing multiprocessing python-multiprocessing


【解决方案1】:

我认为multiprocessing 需要相当长的时间来创建和启动每个进程。我已将程序更改为 arr 大小的 10 倍,并更改了进程的启动方式,并且速度略有加快:

(另请注意python 3)

import time
import multiprocessing, threading
from multiprocessing import Queue
import random

def calc_square_q(numbers,q):
    while q.empty():
        pass
    return calc_square(numbers)

if __name__ == "__main__":

    random.seed(1)   # note how big arr is now vvvvvvv
    arr = [random.randint(1, 11) for i in range(10000000)]
    print("init completed")

    # ...
    # other stuff as before
    # ...

    processes=[]
    q=Queue()
    for arrs in newarr:
        processes.append(multiprocessing.Process(target=calc_square_q, args=(arrs,q)))

    print('start processes')
    for p in processes:
        p.start()  # even tho' each process is started it waits...

    print('join processes')
    q.put(None)   # ... for q to become not empty.
    start_time = time.time()
    for p in processes:
        p.join()

    end_time = time.time()

    print("mp: " + str(end_time - start_time))

还要注意上面我如何在两个不同的循环中创建和启动进程,然后最终加入第三个循环中的进程。

输出:

init completed
serial: 0.53214430809021
split complete
start threads
mt: 0.5551605224609375
start processes
join processes
mp: 0.2800724506378174

arr 的大小又增加了 10 倍:

init completed
serial: 5.8455305099487305
split complete
start threads
mt: 5.411392450332642
start processes
join processes
mp: 1.9705185890197754

是的,我也在 python 2.7 中尝试过,虽然 Threads 似乎更慢。

【讨论】:

  • 您好,感谢您的回复,这也适用于 2.7x 吗?这就是我正在使用的。
  • 抛出“NameError: name 'Queue' is not defined”错误。我该怎么办?尝试导入队列,然后抛出一个不可调用的错误。
  • 我只使用了Queue 来演示启动进程需要多少时间。并行处理作业可能根本不需要它。
  • 事实上,大部分时间可能都花在将大数组传递到每个进程中。
  • 啊,我明白了。因此,如果我正确理解这一点,重要的是首先创建所有流程,然后再运行它们以正确计算时间改进?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-10
  • 2013-11-09
  • 2014-04-23
  • 1970-01-01
相关资源
最近更新 更多