找回密码
 立即注册

QQ登录

只需一步,快速开始

Python使用multiprocessing实现多进程

2024-11-5 00:00| 发布者: 284cc| 查看: 412| 评论: 0

摘要: 目录弁言一、介绍二、创建进程1、导入multiprocessing模块2、创建进程3、启动进程4、进程的状态二、进程间通讯1、队列(Queue)2、管道(Pipe)3、共享内存(Value、Array)4、信号量(Semaphore)5、变乱(Event)6
目录

弁言

各人好,当我们工作中涉及到处置惩罚大量数据、并行计算或并发任务时,Python的multiprocessing模块是一个强盛而实用的工具。通过它,我们可以轻松地使用多核处置惩罚器的优势,将任务分配给多个进程并同时实行,从而进步步伐的性能和服从。在本文中,我们将探索怎样使用multiprocessing模块实现多进程编程。将介绍进程池的概念和用法,以及怎样使用它来管理和调理多个进程。我们还将讨论并发任务的处置惩罚、进程间通讯和结果获取等关键问题,希望能给各人的工作带来一些资助。

一、介绍

Python多进程是一种并行编程模子,允许在Python步伐中同时实行多个进程。每个进程都拥有本身的独立内存空间和实行环境,可以并行地实行任务,从而进步步伐的性能和服从。

优点:

  • 并行处置惩罚:多进程可以同时实行多个任务,充分使用多核处置惩罚器的本领,实现并行处置惩罚。这可以明显进步步伐的性能和服从,特别是在处置惩罚密集型任务或须要大量计算的场景中。

  • 独立性:每个进程都有本身的独立地址空间和实行环境,进程之间互不干扰。这意味着每个进程都可以独立地实行任务,不会受到其他进程的影响。这种独立性使得多进程编程更加健壮和可靠。

  • 内存隔离:由于每个进程都拥有本身的地址空间,多进程之间的数据是相互隔离的。这意味着差别进程之间的变量和数据不会相互影响,镌汰了数据共享和同步的复杂性。

  • 故障隔离:如果一个进程瓦解或出现错误,不会影响其他进程的实行。每个进程是独立的实体,一个进程的故障不会对整个步伐产生致命影响,进步了步伐的稳定性和容错性。

  • 可移植性:多进程编程可以在差别的操作体系上运行,因为进程是操作体系提供的基本概念。这使得多进程编程具有很好的可移植性,可以在差别的平台上部署和运行。

缺点:

  • 资源消耗:每个进程都须要独立的内存空间和体系资源,包括打开的文件、网络毗连等。多进程编程可能会增加体系的资源消耗,尤其是在创建大量进程时。

  • 上下文切换开销:在多进程编程中,进程之间的切换须要生存和规复进程的实行环境,这涉及到上下文切换的开销。频繁的进程切换可能会导致额外的开销,影响步伐的性能。

  • 数据共享与同步:由于多进程之间的数据是相互隔离的,须要通过特定的机制进行数据共享和同步。这可能涉及到进程间通讯(IPC)的复杂性,如队列、管道、共享内存等。正确处置惩罚数据共享和同步是多进程编程中的挑衅之一。

  • 编程复杂性:相比于单线程或多线程编程,多进程编程可能更加复杂。须要思量进程的创建和管理、进程间通讯、数据共享和同步等问题。编写和调试多进程步伐可能须要更多的工作和履历。

进程与线程:

  • 在讨论多进程之前,须要明白进程(Process)和线程(Thread)的概念。
  • 进程是计算机中正在运行的步伐的实例。每个进程都有本身的地址空间、数据栈和控制信息,可以独立实行任务。
  • 线程是进程中的一个实行单位,可以看作是轻量级的进程。多个线程共享同一进程的资源,包括内存空间、文件形貌符等。

多进程编程在并行处置惩罚和资源隔离方面具有明显的优势,但也涉及到资源消耗、上下文切换开销、数据共享和同步等问题。在现实应用中,开发者应权衡利弊,根据具体场景选择恰当的编程模子和工具。

二、创建进程

在Python中,可以使用[code]multiprocessing[/code]模块来创建和管理进程。该模块提供了丰富的类和函数,用于创建、启动和管理进程。

1、导入multiprocessing模块

在使用[code]multiprocessing[/code]模块之前,须要先导入它:

[code]import multiprocessing[/code]

2、创建进程

可以使用[code]multiprocessing.Process[/code]类来创建进程对象。须要传入一个目标函数作为进程的实行逻辑。可以通过继承[code]multiprocessing.Process[/code]类来自定义进程类。

[code]import multiprocessing def worker(): # 进程实行的逻辑 if __name__ == '__main__': process = multiprocessing.Process(target=worker)[/code]

在上面的示例中,[code]worker[/code]函数是进程的实行逻辑。进程对象创建后,可以通过设置参数、调用方法等来设置进程。

3、启动进程

通过调用进程对象的[code]start()[/code]方法,可以启动进程。进程会在背景开始实行。

[code]process.start()[/code]

4、进程的状态

进程对象提供了一些方法来获取和管理进程的状态:

  • [code]is_alive()[/code]:查抄进程是否正在运行。
  • [code]join([timeout])[/code]:等待进程结束。可选参数[code]timeout[/code]指定等待的最长时间。
[code]if process.is_alive(): print("进程正在运行") process.join()[/code]

二、进程间通讯

进程间通讯(Inter-Process Communication,IPC)是指差别进程之间进行数据互换和共享信息的机制。在多进程编程中,进程之间通常须要进行数据传输、共享状态或进行同步操作。Python提供了多种进程间通讯的机制,包括队列(Queue)、管道(Pipe)、共享内存(Value、Array)等。

1、队列(Queue)

队列是一种常用的进程间通讯方式,通过队列可以实现进程之间的数据传输。Python的[code]multiprocessing[/code]模块提供了[code]Queue[/code]类来实现多进程之间的队列通讯。进程可以通过[code]put()[/code]方法将数据放入队列,其他进程则可以通过[code]get()[/code]方法从队列中获取数据。

[code]from multiprocessing import Queue # 创建队列 queue = Queue() # 进程1放入数据 queue.put(data) # 进程2获取数据 data = queue.get()[/code]

2、管道(Pipe)

管道是另一种常用的进程间通讯方式,通过管道可以实现进程之间的双向通讯。Python的[code]multiprocessing[/code]模块提供了[code]Pipe[/code]类来创建管道对象。[code]Pipe()[/code]方法返回两个毗连的管道端,一个用于发送数据,另一个用于吸收数据。

[code]from multiprocessing import Pipe # 创建管道 conn1, conn2 = Pipe() # 进程1发送数据 conn1.send(data) # 进程2吸收数据 data = conn2.recv()[/code]

3、共享内存(Value、Array)

共享内存是一种在多进程之间共享数据的高效方式。Python的[code]multiprocessing[/code]模块提供了[code]Value[/code]和[code]Array[/code]类来实现进程间共享数据。[code]Value[/code]用于共享单个值,而[code]Array[/code]用于共享数组。

[code]from multiprocessing import Value, Array # 创建共享值 shared_value = Value('i', 0) # 创建共享数组 shared_array = Array('i', [1, 2, 3, 4, 5])[/code]

在创建共享值和共享数组时,须要指定数据类型(如整数、浮点数)和初始值。进程可以通过读写共享值和共享数组来进行进程间的数据共享。

4、信号量(Semaphore)

信号量是一种用于控制对共享资源的访问的机制。在多进程编程中,信号量可以用于限制同时访问某个共享资源的进程数目。

[code]from multiprocessing import Semaphore, Process import time def worker(semaphore, name): semaphore.acquire() print("Worker", name, "acquired semaphore") time.sleep(2) print("Worker", name, "released semaphore") semaphore.release() semaphore = Semaphore(2) processes = [] for i in range(5): p = Process(target=worker, args=(semaphore, i)) processes.append(p) p.start() for p in processes: p.join()[/code]

在上述例子中,创建了一个信号量,初始值为2。然后创建了5个进程,每个进程在实行前会尝试获取信号量,如果信号量的值大于0,则乐成获取;否则,进程将被壅闭,直到有进程释放信号量。每个进程获取信号量后,会实行一段任务,并在实行完后释放信号量。

5、变乱(Event)

变乱是一种用于多进程间通讯的同步机制,它允许一个或多个进程等待某个变乱的发生,然后再继续实行。

[code]from multiprocessing import Event, Process import time def worker(event, name): print("Worker", name, "waiting for event") event.wait() print("Worker", name, "received event") time.sleep(2) print("Worker", name, "completed task") event = Event() processes = [] for i in range(3): p = Process(target=worker, args=(event, i)) processes.append(p) p.start() time.sleep(3) event.set() for p in processes: p.join()[/code]

在上述例子中,创建了一个变乱。然后创建了3个进程,每个进程在实行前会等待变乱的发生,即调用event.wait()方法。主进程休眠3秒后,设置变乱的状态为已发生,即调用event.set()方法。此时,全部等待变乱的进程将被唤醒,并继续实行任务。

6、条件变量(Condition)

条件变量是一种用于多进程间协调和同步的机制,它可以用于控制多个进程之间的实行次序。

[code]from multiprocessing import Condition, Process import time def consumer(condition): with condition: print("Consumer is waiting") condition.wait() print("Consumer is consuming the product") def producer(condition): with condition: time.sleep(2) print("Producer is producing the product") condition.notify() condition = Condition() consumer_process = Process(target=consumer, args=(condition,)) producer_process = Process(target=producer, args=(condition,)) consumer_process.start() producer_process.start() consumer_process.join() producer_process.join()[/code]

在上述例子中,创建了一个条件变量。然后创建了一个消耗者进程和一个生产者进程。消耗者进程在实行前等待条件的满足,即调用condition.wait()方法。生产者进程休眠2秒后,天生产品并通过condition.notify()方法通知消耗者。消耗者收到通知后继续实行任务。

三、进程间同步

进程间同步是确保多个进程按照特定次序实行或在共享资源上进行互斥访问的一种机制。进程间同步的目标是制止竞态条件(race condition)和数据差别等的问题。Python提供了多种机制来实现进程间的同步,包括锁(Lock)、信号量(Semaphore)、变乱(Event)、条件变量(Condition)等。

1、锁(Lock)

锁是一种最基本的同步机制,用于掩护共享资源的互斥访问,确保在任意时候只有一个进程可以访问共享资源。在Python中,可以使用[code]multiprocessing[/code]模块的[code]Lock[/code]类来实现锁。

[code]from multiprocessing import Lock, Process lock = Lock() def worker(lock, data): lock.acquire() try: # 对共享资源进行操作 pass finally: lock.release() processes = [] for i in range(5): p = Process(target=worker, args=(lock, i)) processes.append(p) p.start() for p in processes: p.join()[/code]

在上述例子中,每个进程在访问共享资源之前会先获取锁,然后在完成操作后释放锁。如许可以确保在同一时候只有一个进程可以大概访问共享资源,制止数据竞争问题。

2、信号量(Semaphore)

信号量是一种更为机动的同步机制,它允许多个进程同时访问某个资源,但限制同时访问的进程数目。在Python中,可以使用[code]multiprocessing[/code]模块的[code]Semaphore[/code]类来实现信号量。

[code]from multiprocessing import Semaphore, Process semaphore = Semaphore(2) def worker(semaphore, data): semaphore.acquire() try: # 对共享资源进行操作 pass finally: semaphore.release() processes = [] for i in range(5): p = Process(target=worker, args=(semaphore, i)) processes.append(p) p.start() for p in processes: p.join()[/code]

在上述例子中,创建了一个初始值为2的信号量。每个进程在访问共享资源之前会尝试获取信号量,只有当信号量的值大于0时才能获取乐成,否则进程将被壅闭。获取乐成后,进程可以进行操作,并在完成后释放信号量。

3、变乱(Event)

变乱是一种同步机制,用于实现进程之间的等待和通知机制。一个进程可以等待变乱的发生,而另一个进程可以触发变乱的发生。在Python中,可以使用[code]multiprocessing[/code]模块的[code]Event[/code]类来实现变乱。

[code]from multiprocessing import Event, Process event = Event() def worker(event, data): event.wait() # 实行任务 processes = [] for i in range(5): p = Process(target=worker, args=(event, i)) processes.append(p) p.start() # 触发变乱的发生 event.set() for p in processes: p.join()[/code]

在上述例子中,多个进程在实行任务前会等待变乱的发生,即调用[code]event.wait()[/code]方法。主进程通过调用[code]event.set()[/code]方法来触发变乱的发生,进而唤醒等待的进程继续实行。

4、条件变量(Condition)

条件变量是一种复杂的同步机制,它允许进程按照特定的条件等待和通知。在Python中,可以使用[code]multiprocessing[/code]模块的[code]Condition[/code]类来实现条件变量。

[code]from multiprocessing import Condition, Process condition = Condition() def consumer(condition(续): def consumer(condition, data): with condition: while True: # 查抄条件是否满足 while not condition_is_met(): condition.wait() # 从共享资源中消耗数据 def producer(condition, data): with condition: # 天生数据并更新共享资源 condition.notify_all() processes = [] for i in range(5): p = Process(target=consumer, args=(condition, i)) processes.append(p) p.start() producer_process = Process(target=producer, args=(condition, data)) producer_process.start() for p in processes: p.join() producer_process.join()[/code]

在上述例子中,消耗者进程在实行任务前会查抄条件是否满足,如果条件不满足,则调用condition.wait()方法等待条件的满足。生产者进程天生数据并更新共享资源后,调用condition.notify_all()方法通知全部等待的消耗者进程条件已满足。被唤醒的消耗者进程会重新查抄条件并实行任务。

四、进程池

进程池是一种用于管理和调理多个进程的机制,它可以有效地处置惩罚并行任务和进步步伐的性能。进程池在Python中通常使用[code]multiprocessing[/code]模块提供的[code]Pool[/code]类来实现。

进程池的工作原理如下:

  1. 创建进程池时,会启动指定数目标进程,并将它们放入池中。
  2. 池中的进程会等待主进程提交任务。
  3. 主进程通过提交任务给进程池,将任务分配给空闲的进程。
  4. 进程池中的进程实行任务,并将结果返回给主进程。
  5. 主进程获取任务的结果,继续实行其他操作。
  6. 当全部任务完成后,主进程关闭进程池。

1、创建进程池

要使用进程池,起首须要创建一个[code]Pool[/code]对象,可以指定池中的进程数目。通常,可以使用[code]multiprocessing.cpu_count()[/code]函数来获取当前体系的CPU焦点数,然后根据须要来指定进程池的巨细。

[code]from multiprocessing import Pool, cpu_count pool = Pool(processes=cpu_count())[/code]

在上述例子中,创建了一个进程池,进程数目与体系的CPU焦点数相同。

2、提交任务

一旦创建了进程池,就可以使用[code]apply()[/code]、[code]map()[/code]或[code]imap()[/code]方法来提交任务给进程池。

apply()方法用于提交单个任务,并等待任务完成后返回结果。

[code]result = pool.apply(function, args=(arg1, arg2))[/code]

map()方法用于提交多个任务,并按照任务提交的次序返回结果列表。

[code]results = pool.map(function, iterable)[/code]

imap()方法也用于提交多个任务,但可以通过迭代器逐个获取结果,而不须要等待全部任务完成。

[code]results = pool.imap(function, iterable)[/code]

在上述例子中,[code]function[/code]体现要实行的函数,[code]args[/code]是函数的参数,[code]iterable[/code]是一个可迭代对象,可以是列表、元组等。

3、获取结果

对于[code]apply()[/code]方法,调用后会壅闭主进程,直到任务完成并返回结果。对于[code]map()[/code]方法,调用后会等待全部任务完成,并按照任务提交的次序返回结果列表。对于[code]imap()[/code]方法,可以通过迭代器逐个获取结果。

[code]for result in results: print(result)[/code]

在上述例子中,使用[code]for[/code]循环逐个获取结果并进行处置惩罚。

4、关闭进程池

在全部任务完成后,须要显式地关闭进程池,以释放资源。

[code]pool.close() pool.join()[/code]

调用[code]close()[/code]方法后,进程池将不再接受新的任务。调用[code]join()[/code]方法会壅闭主进程,直到全部任务都已完成。

5、使用进程池的示例

[code]from multiprocessing import Pool # 定义一个任务函数 def square(x): return x ** 2 if __name__ == '__main__': # 创建进程池 with Pool(processes=4) as pool: # 提交任务给进程池 results = pool.map(square, range(10)) # 打印结果 print(results)[/code]

在上述示例中,起首定义了一个任务函数square,它接受一个数值作为参数,并返回该数值的平方。

在if __name__ == '__main__':中,创建了一个进程池,指定进程数目为4。使用with语句可以确保进程池在使用完毕后被正确关闭。

然后,通过pool.map(square, range(10))将任务提交给进程池。map()方法会将任务函数square和一个可迭代对象range(10)作为参数,它会将可迭代对象中的每个元素依次传递给任务函数进行处置惩罚,并返回结果列表。末了,打印结果列表,即每个数值的平方。

须要注意的是,在使用进程池时,须要将主步伐代码放在if __name__ == '__main__':中,以确保在子进程中不会重复实行主步伐的代码。

以下是一个更加复杂的多进程示例,展示了怎样使用进程池处置惩罚多个任务,并在任务完成时获取结果。

[code]import time from multiprocessing import Pool # 定义一个任务函数 def process_data(data): # 模拟耗时操作 time.sleep(1) # 返回处置惩罚结果 return data.upper() if __name__ == '__main__': # 创建进程池 with Pool(processes=3) as pool: # 准备数据 data_list = ['apple', 'banana', 'cherry', 'date', 'elderberry'] # 提交任务给进程池 results = [pool.apply_async(process_data, args=(data,)) for data in data_list] # 等待全部任务完成并获取结果 final_results = [result.get() for result in results] # 打印结果 for result in final_results: print(result)[/code]

在上述示例中,除了使用进程池的map()方法提交任务之外,还使用了apply_async()方法来异步提交任务,并通过get()方法获取任务的结果。

在if __name__ == '__main__':中,创建了一个进程池,指定进程数目为3。使用with语句可以确保进程池在使用完毕后被正确关闭。然后,准备了一个数据列表data_list,此中包含了须要处置惩罚的数据。

通过列表推导式,使用pool.apply_async(process_data, args=(data,))将任务异步提交给进程池。apply_async()方法会将任务函数process_data和数据data作为参数,返回一个AsyncResult对象,体现异步任务的结果。将这些对象存储在results列表中。

接下来,使用列表推导式,通过result.get()方法等待全部任务完成并获取结果,将结果存储在final_results列表中。末了,使用for循环遍历final_results列表,并打印每个任务的处置惩罚结果。

进程池的优点是可以自动管理和调理多个进程,充分使用体系资源,进步步伐的并行实行本领。通过公道设置进程池的巨细,可以在不太过消耗体系资源的情况下,实现最佳的并发结果。但须要注意的是,进程池实用于那些须要并行实行的任务,而不实用于IO密集型任务,因为进程池中的进程是通过复制主进程来创建的,而IO密集型任务更恰当使用线程池来实现并发。

以上就是Python使用multiprocessing实现多进程的具体内容,更多关于Python multiprocessing多线程的资料请关注脚本之家其它相干文章!


来源:https://www.jb51.net/python/328663rc3.htm
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

最新评论

关闭

站长推荐上一条 /6 下一条

QQ|手机版|小黑屋|梦想之都-俊月星空 ( 粤ICP备18056059号 )|网站地图

GMT+8, 2025-7-1 19:08 , Processed in 0.040083 second(s), 19 queries .

Powered by Mxzdjyxk! X3.5

© 2001-2025 Discuz! Team.

返回顶部