并行编程是一种编程模型,允许程序在多个处理器或内核上同时运行多个任务。该模型旨在更有效地使用处理器资源、减少处理时间并提高性能。
为了用图像说明并行编程,我们可以想象我们遇到了一个问题。在开始并行处理之前,我们将这个问题分成更小的子部分。我们假设这些子部分彼此独立并且彼此不了解。每个子问题都被转化为更小的任务或指令。这些任务以适合并行工作的方式组织。例如,可以创建许多指令来对数据集执行相同的操作。然后这些任务被分配给不同的处理器。每个处理器独立且并行地处理其分配的指令。这个过程显着减少了总处理时间,使我们能够更有效地使用资源。
Python 提供了多种用于并行编程的工具和模块。
**多处理
**它允许程序同时运行多个进程,从而利用真正的并行性。多处理模块克服了 GIL(全局解释器锁)的限制,允许在多核处理器上实现全部性能。
全局解释器锁(GIL)是流行的 Python 实现(称为 CPython)中使用的一种机制。 GIL 一次只允许一个线程执行 Python 字节码。当在 Python 中使用多线程时,这种结构会限制真正的并行性。
*平方和立方计算示例
*
from multiprocessing import Process def print_square(numbers): for n in numbers: print(f"Square of {n} is {n * n}") def print_cube(numbers): for n in numbers: print(f"Cube of {n} is {n * n * n}") if __name__ == "__main__": numbers = [2, 3, 4, 5] # İşlemler (processes) oluşturma process1 = Process(target=print_square, args=(numbers,)) process2 = Process(target=print_cube, args=(numbers,)) # İşlemleri başlatma process1.start() process2.start() # İşlemlerin tamamlanmasını bekleme process1.join() process2.join()
为什么我们需要多重处理 我们可以用厨师和厨房的类比来解释多重处理的需求。您可以将厨师独自在厨房做饭视为单进程程序。我们可以将其比作多处理,即多个厨师在同一个厨房一起工作。
单一流程 - 单一烹饪
厨房里只有一名厨师。这位厨师将制作三道不同的菜肴:开胃菜、主菜和甜点。每道菜依次制作:
他准备并完成了开胃菜。
他继续主菜并完成它。
最后,他做了甜点。
问题:
无论厨师有多快,他或她都会轮流,这会浪费厨房时间。
如果需要同时煮三种不同的菜肴,时间会更长。
多重处理 - 许多厨师
现在想象一下同一个厨房里有三个厨师。每个人都在准备不同的菜肴:
开胃菜由一名厨师制作。
第二位厨师准备主菜。
第三位厨师做甜点。
优点:
三道菜同时制作,大大减少了总时间。
每个厨师独立做自己的工作,不受其他人的影响。
在 Python 中的进程之间共享数据
在Python中,可以使用多处理模块在不同进程之间共享数据。但是,每个进程都使用自己的内存空间。因此,使用特殊的机制在进程之间共享数据。
from multiprocessing import Process def print_square(numbers): for n in numbers: print(f"Square of {n} is {n * n}") def print_cube(numbers): for n in numbers: print(f"Cube of {n} is {n * n * n}") if __name__ == "__main__": numbers = [2, 3, 4, 5] # İşlemler (processes) oluşturma process1 = Process(target=print_square, args=(numbers,)) process2 = Process(target=print_cube, args=(numbers,)) # İşlemleri başlatma process1.start() process2.start() # İşlemlerin tamamlanmasını bekleme process1.join() process2.join()
当我们检查代码示例时,我们看到结果列表为空。主要原因是使用多处理创建的进程在自己的内存空间中工作,独立于主进程。由于这种独立性,子进程中所做的更改不会直接反映在主进程中的变量中。
Python 提供了以下共享数据的方法:
**1。共享内存
**Value 和 Array 对象用于在操作之间共享数据。
值:共享单一数据类型(例如数字)。
数组:用于共享数据数组。
import multiprocessing result = [] def square_of_list(mylist): for num in mylist: result.append(num**2) return result mylist= [1,3,4,5] p1 = multiprocessing.Process(target=square_of_list,args=(mylist,)) p1.start() p1.join() print(result) # [] Boş Liste
**2。队列
**它使用 FIFO(先进先出)结构在进程之间传输数据。
multiprocessing.Queue 允许多个进程发送和接收数据。
from multiprocessing import Process, Value def increment(shared_value): for _ in range(1000): shared_value.value += 1 if __name__ == "__main__": shared_value = Value('i', 0) processes = [Process(target=increment, args=(shared_value,)) for _ in range(5)] for p in processes: p.start() for p in processes: p.join() print(f"Sonuç: {shared_value.value}")
**3。管道
**multiprocessing.Pipe 提供两个进程之间的双向数据传输。
它可用于发送和接收数据。
from multiprocessing import Process, Queue def producer(queue): for i in range(5): queue.put(i) # Kuyruğa veri ekle print(f"Üretildi: {i}") def consumer(queue): while not queue.empty(): item = queue.get() print(f"Tüketildi: {item}") if __name__ == "__main__": queue = Queue() producer_process = Process(target=producer, args=(queue,)) consumer_process = Process(target=consumer, args=(queue,)) producer_process.start() producer_process.join() consumer_process.start() consumer_process.join()
*进程之间的填充
*“进程之间的填充”通常用于进程内存组织或避免访问多个进程之间共享的数据时的数据对齐和冲突问题。
这个概念在缓存行错误共享等情况下尤其重要。当多个进程尝试同时使用共享内存时,错误共享可能会导致性能损失。这是由于现代处理器中缓存行的共享。
**进程之间的同步
**使用Python中的多处理模块,多个进程可以同时运行。然而,当多个进程需要访问相同的数据时,使用同步非常重要。这是确保数据一致性并避免竞争条件等问题所必需的。
from multiprocessing import Process, Pipe def send_data(conn): conn.send([1, 2, 3, 4]) conn.close() if __name__ == "__main__": parent_conn, child_conn = Pipe() process = Process(target=send_data, args=(child_conn,)) process.start() print(f"Alınan veri: {parent_conn.recv()}") # Veri al process.join()
锁一次只允许一个进程访问共享数据。
在使用锁的进程完成之前,其他进程会等待。
**多线程
多线程是一种并行编程模型,允许程序同时运行多个线程。线程是在同一进程中运行的较小的独立代码单元,旨在通过共享资源实现更快、更高效的处理。
在Python中,threading模块用于开发多线程应用程序。然而,由于Python的全局解释器锁(GIL)机制,多线程在CPU密集型任务上提供的性能有限。因此,多线程通常是 I/O 密集型任务的首选。
线程是我们程序中的指令序列。
from multiprocessing import Process def print_square(numbers): for n in numbers: print(f"Square of {n} is {n * n}") def print_cube(numbers): for n in numbers: print(f"Cube of {n} is {n * n * n}") if __name__ == "__main__": numbers = [2, 3, 4, 5] # İşlemler (processes) oluşturma process1 = Process(target=print_square, args=(numbers,)) process2 = Process(target=print_cube, args=(numbers,)) # İşlemleri başlatma process1.start() process2.start() # İşlemlerin tamamlanmasını bekleme process1.join() process2.join()
**线程同步
**线程同步是当多个线程同时访问相同资源时用于保证数据一致性和顺序的技术。在Python中,threading模块提供了几种用于同步的工具。
**为什么需要线程同步?
**比赛条件:
当两个或多个线程同时访问共享资源时,可能会出现数据不一致的情况。
例如,一个线程可能读取数据,而另一个线程更新相同的数据。
*数据一致性:
*
需要线程之间的协调来确保共享资源正确更新。
Python 中的同步工具示例
**1.锁
**当一个线程获取锁时,它会等待锁被释放,然后其他线程才能访问同一资源。
import multiprocessing result = [] def square_of_list(mylist): for num in mylist: result.append(num**2) return result mylist= [1,3,4,5] p1 = multiprocessing.Process(target=square_of_list,args=(mylist,)) p1.start() p1.join() print(result) # [] Boş Liste
2 活动
from multiprocessing import Process, Value def increment(shared_value): for _ in range(1000): shared_value.value += 1 if __name__ == "__main__": shared_value = Value('i', 0) processes = [Process(target=increment, args=(shared_value,)) for _ in range(5)] for p in processes: p.start() for p in processes: p.join() print(f"Sonuç: {shared_value.value}")
**结论:
**线程同步对于防止线程访问共享资源时出现数据不一致至关重要。 Python中,Lock、RLock、Semaphore、Event、Condition等工具根据同步需求提供了有效的解决方案。使用哪种工具取决于应用程序的需求和同步要求。
以上是Python 中的进程管理:并行编程基础的详细内容。更多信息请关注PHP中文网其他相关文章!