【Python】Python进程池multiprocessing.Pool八个函数对比:apply、apply_async、map、map_async、imap、starmap...

1、apply apply_async 一次执行一个任务,但 apply_async 可以异步执行,因而也可以实现并发。

2、map 和 map_asyncapply 和 apply_async 的区别是可以并发执行任务。

3、starmap 和 starmap_asyncmap 和 map_async 的区别是,starmap 和 starmap_async 可以传入多个参数。

4、imap 和 imap_unordered 与 map_async 同样是异步,区别是:

map_async生成子进程时使用的是list,而imap和 imap_unordered则是Iterable,map_async效率略高,而imap和 imap_unordered内存消耗显著的小。

在处理结果上,imap 和 imap_unordered 可以尽快返回一个Iterable的结果,而map_async则需要等待全部Task执行完毕,返回list。

而imap 和 imap_unordered 的区别是:imap 和 map_async一样,都按顺序等待Task的执行结果,而imap_unordered则不必。 imap_unordered返回的Iterable,会优先迭代到先执行完成的Task。 不理解的看最下面的一组例子。

 

你可以自己去写一些小demo跑一下,观察一下它们之间运行方式的一些区别。下面是我跑的一些demo:

一、单次执行apply 和 apply_async

1、单次同步执行apply

一个任务执行完再进行下一个任务

import multiprocessing
import time
 
def func(msg):
    print("msg:", msg)
    time.sleep(2)
    print("end")
 
if __name__ == "__main__":
    pool = multiprocessing.Pool()
    for i in range(2):
        msg = "hello %d" %(i)
        pool.apply(func, (msg, ))
 
    print("Mark~ Mark~ Mark~~~~~~~~~~~~~~~~~~~~~~")
    pool.close()
    pool.join()
    print("Sub-process(es) done.")

# 输出:
msg: hello 0
end
msg: hello 1
end
Mark~ Mark~ Mark~~~~~~~~~~~~~~~~~~~~~~
Sub-process(es) done.

2、单次异步执行apply_async

单次启动一个任务,但是异步执行,启动后不等这个进程结束又开始执行新任务

import multiprocessing
import time

def func(msg):
    print("msg:", msg)
    time.sleep(1)
    print("end")

if __name__ == "__main__":
    pool = multiprocessing.Pool(processes = 2)
    for i in range(2):
        msg = "hello %d" %(i)
        pool.apply_async(func, (msg, ))   #维持执行的进程总数为processes,当一个进程执行完毕后会添加新的进程进去

    print("Mark~ Mark~ Mark~~~~~~~~~~~~~~~~~~~~~~")
    pool.close()
    pool.join()   #调用join之前,先调用close函数,否则会出错。执行完close后不会有新的进程加入到pool,join函数等待所有子进程结束
    print("Sub-process(es) done.")

# 输出
Mark~ Mark~ Mark~~~~~~~~~~~~~~~~~~~~~~
msg: hello 0
msg: hello 1
end
end
Sub-process(es) done.

 

二、多任务执行map 和 map_async

1、阻塞到任务列表中所有任务完成再往下执行 map

import multiprocessing
import time

def func(msg):
    print("msg:", msg)
    time.sleep(2)
    print("end")

if __name__ == "__main__":
    pool = multiprocessing.Pool(2)
    pool.map(func, range(2))

    print("Mark~ Mark~ Mark~~~~~~~~~~~~~~~~~~~~~~")
    pool.close()
    pool.join()
    print("Sub-process(es) done.")

# 输出(注意Mark~位置):
msg: 0
msg: 1
end
end
Mark~ Mark~ Mark~~~~~~~~~~~~~~~~~~~~~~
Sub-process(es) done.

2、异步,任务执行时不阻塞 map_async

import multiprocessing
import time

def func(msg):
    print("msg:", msg)
    time.sleep(2)
    print("end")

if __name__ == "__main__":
    pool = multiprocessing.Pool(2)
    pool.map_async(func, range(2))

    print("Mark~ Mark~ Mark~~~~~~~~~~~~~~~~~~~~~~")
    pool.close()
    pool.join()
    print("Sub-process(es) done.")

# 输出:
Mark~ Mark~ Mark~~~~~~~~~~~~~~~~~~~~~~
msg: 0
msg: 1
end
end
Sub-process(es) done.

 

三、传入多个参数starmap 和 starmap_async

与二中 map 和 map_async 的区别是,这两个函数可以传入多个参数

1、阻塞starmap

import multiprocessing
import time

def func(msg1, msg2):
    print("msg1:", msg1, "msg2:", msg2)
    time.sleep(2)
    print("end")

if __name__ == "__main__":
    pool = multiprocessing.Pool(2)
    msgs = [(1,1),(2,2)]
    pool.starmap(func, msgs)

    print("Mark~ Mark~ Mark~~~~~~~~~~~~~~~~~~~~~~")
    pool.close()
    pool.join()
    print("Sub-process(es) done.")

# 输出
msg1: 1 msg2: 1
msg1: 2 msg2: 2
end
end
Mark~ Mark~ Mark~~~~~~~~~~~~~~~~~~~~~~
Sub-process(es) done.

2、异步starmap_async

import multiprocessing
import time

def func(msg1, msg2):
    print("msg1:", msg1, "msg2:", msg2)
    time.sleep(2)
    print("end")

if __name__ == "__main__":
    pool = multiprocessing.Pool(2)
    msgs = [(1, 1), (2, 2)]
    pool.starmap_async(func, msgs)

    print("Mark~ Mark~ Mark~~~~~~~~~~~~~~~~~~~~~~")
    pool.close()
    pool.join()
    print("Sub-process(es) done.")

# 输出:
Mark~ Mark~ Mark~~~~~~~~~~~~~~~~~~~~~~
msg1: 1 msg2: 1
msg1: 2 msg2: 2
end
end
Sub-process(es) done.

 

四、获取进程池中的结果——map_async与imap和imap_unordered的区别

注意:在获取进程池中的结果时,map_async、imap、imap_unordered三个方法都会阻塞。

map_async 与 imap、imap_unordered区别是:map_async需要等待所有Task执行结束后返回list,而imap 和 imap_unordered 可以尽快返回一个Iterable的结果。

imap 和 imap_unordered 的区别是:imap 和 map_async一样,都按顺序等待Task的执行结果,而imap_unordered则不必。 imap_unordered返回的Iterable,会优先迭代到先执行完成的Task。

1、list、有序——map_async

import multiprocessing
import time

def func(msg):
    print("msg:", msg)
    time.sleep(4-msg)
    return msg

if __name__ == "__main__":
    pool = multiprocessing.Pool(3)
    results = pool.map_async(func, range(3))
    for res in results.get():
        print(res)

    print("Mark~ Mark~ Mark~~~~~~~~~~~~~~~~~~~~~~")
    pool.close()
    pool.join()

    print("Sub-process(es) done.")

# 输出
msg: 0
msg: 1
msg: 2
0
1
2
Mark~ Mark~ Mark~~~~~~~~~~~~~~~~~~~~~~
Sub-process(es) done.

2、iterate、有序——imap

import multiprocessing
import time

def func(msg):
    print("msg: ", msg)
    time.sleep(4-msg)
    return msg

if __name__ == "__main__":
    pool = multiprocessing.Pool(3)
    results = pool.imap(func, range(3))
    for res in results:
        print("res: ",res)

    print("Mark~ Mark~ Mark~~~~~~~~~~~~~~~~~~~~~~")
    pool.close()
    pool.join()

    print("Sub-process(es) done.")

# 输出
msg: 0
msg: 1
msg: 2
res: 0
res: 1
res: 2
Mark~ Mark~ Mark~~~~~~~~~~~~~~~~~~~~~~
Sub-process(es) done.

3、iterate、无序——imap_unordered

import multiprocessing
import time

def func(msg):
    print("msg: ", msg)
    time.sleep(4-msg)
    return msg

if __name__ == "__main__":
    pool = multiprocessing.Pool(3)
    results = pool.imap_unordered(func, range(3))
    for res in results:
        print("res: ", res)

    print("Mark~ Mark~ Mark~~~~~~~~~~~~~~~~~~~~~~")
    pool.close()
    pool.join()

    print("Sub-process(es) done.")

# 输出
msg: 0
msg: 1
msg: 2
res: 2
res: 1
res: 0
Mark~ Mark~ Mark~~~~~~~~~~~~~~~~~~~~~~
Sub-process(es) done.

参考:

1、https://note.qidong.name/2018/11/python-multiprocessing/

2、https://miraachan.github.io/2018/11/20/20/

Pythonmultiprocessing.Pool模块和multiprocessing.dummy.Pool模块都是用于创建进程和线程的工具。 进程(multiprocessing.Pool)是一组维护在进程中的工作者,它们可以并行地执行任务。该模块是基于multiprocessing模块实现的,它通过创建多个进程来并行执行任务。 下面是一个创建进程的示例: ``` python import multiprocessing def worker(process_num): print("Process %d is working" % process_num) if __name__ == '__main__': pool = multiprocessing.Pool(processes=4) for i in range(5): pool.apply_async(worker, args=(i,)) pool.close() pool.join() ``` 上面的示例中,我们创建了一个包含4个进程进程,并向进程中提交了5个任务,每个任务调用worker函数并传递一个进程编号作为参数。我们使用apply_async方法向进程中提交任务,并使用close和join方法管理进程。 线程(multiprocessing.dummy.Pool)是一组维护在线程中的工作者,它们可以并行地执行任务。该模块是基于threading模块实现的,它通过创建多个线程来并行执行任务。 下面是一个创建线程的示例: ``` python from multiprocessing.dummy import Pool import time def worker(thread_num): print("Thread %d is working" % thread_num) time.sleep(1) if __name__ == '__main__': pool = Pool(4) for i in range(5): pool.apply_async(worker, args=(i,)) pool.close() pool.join() ``` 上面的示例中,我们创建了一个包含4个线程的线程,并向线程中提交了5个任务,每个任务调用worker函数并传递一个线程编号作为参数。我们使用apply_async方法向线程中提交任务,并使用close和join方法管理线程。 需要注意的是,线程进程的用法基本相同,但是由于线程在Python中不能真正地并行执行,因此线程的性能可能比进程差。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值