Hướng dẫn superfast python multiprocessing - đa xử lý python siêu nhanh

Lớp nhóm đa xử lý Python cho phép bạn tạo và quản lý các nhóm quy trình trong Python.Python Multiprocessing Pool class allows you to create and manage process pools in Python.

Show

Mặc dù nhóm đa xử lý đã có sẵn trong Python trong một thời gian dài, nhưng nó không được sử dụng rộng rãi, có lẽ vì những hiểu lầm về khả năng và hạn chế của các quy trình và luồng trong Python.Multiprocessing Pool has been available in Python for a long time, it is not widely used, perhaps because of misunderstandings of the capabilities and limitations of Processes and Threads in Python.

Hướng dẫn này cung cấp một đánh giá chi tiết và toàn diện về nhóm Themultiprocessing trong Python, bao gồm cách thức hoạt động, cách sử dụng nó, các câu hỏi phổ biến và thực tiễn tốt nhất.Multiprocessing Pool in Python, including how it works, how to use it, common questions, and best practices.

Đây là một hướng dẫn lớn hơn 26.000 từ. Bạn có thể muốn đánh dấu nó để bạn có thể tham khảo nó khi bạn phát triển các chương trình đồng thời của mình.

Hãy để lặn trong.

  • Các quy trình của Python và nhu cầu về các nhóm quy trình
    • Quá trình Python là gì
    • Nhóm quy trình là gì
    • Các hồ bơi đa xử lý trong Python
  • Vòng đời của đa bộ xử lý.pool
    • Bước 1. Tạo nhóm quy trình
    • Bước 2. Gửi nhiệm vụ đến nhóm quy trình
    • Bước 3. Chờ các nhiệm vụ hoàn thành (tùy chọn)
    • Bước 4. Tắt máy quy trình
  • Ví dụ về nhóm đa xử lý
    • Băm một từ điển của các từ từng người một
    • Hash một từ điển của các từ đồng thời với bản đồ ()
  • Cách định cấu hình nhóm đa xử lý
    • Cách định cấu hình số lượng quy trình công nhân
    • Cách định cấu hình chức năng khởi tạo
    • Cách định cấu hình các nhiệm vụ tối đa cho mỗi đứa trẻ
    • Cách định cấu hình ngữ cảnh
  • Nhiệm vụ phát hành nhóm đa xử lý
    • Cách sử dụng pool.apply ()
    • Cách sử dụng pool.apply_async ()
    • Cách sử dụng pool.map ()
    • Cách sử dụng pool.map_async ()
    • Cách sử dụng pool.imap ()
    • Cách sử dụng pool.imap_unordered ()
    • Cách sử dụng pool.starmap ()
    • Cách sử dụng pool.starmap_async ()
    • Cách chọn phương pháp
  • Cách sử dụng Asyncresult chi tiết
    • Làm thế nào để có được một đối tượng không liên quan
    • Làm thế nào để có được kết quả
    • Làm thế nào để đợi để hoàn thành
    • Cách kiểm tra xem các nhiệm vụ đã hoàn thành
    • Cách kiểm tra xem các nhiệm vụ có thành công không
  • Các chức năng gọi lại nhóm đa xử lý
    • Cách định cấu hình chức năng gọi lại
    • Cách định cấu hình chức năng gọi lại lỗi
  • Đa xử lý các mẫu sử dụng phổ biến
    • Mẫu 1: Mẫu bản đồ () và lặp lại kết quả
    • Mẫu 2: Ứng dụng_async () và quên mẫu
    • Mẫu 3: map_async () và quên mẫu
    • Mẫu 4: imap_unordered () và sử dụng làm mẫu đã hoàn thành
    • Mẫu 5: imap_unordered () và đợi mẫu đầu tiên
  • Khi nào sử dụng nhóm đa xử lý
    • Sử dụng Multiprocessing.Pool khi
    • Sử dụng nhiều bộ xử lý.pool khi
    • Don Tiết sử dụng đa xử lý.pool khi
    • Don lồng sử dụng các quy trình cho các nhiệm vụ ràng buộc IO (có thể)
    • Sử dụng các quy trình cho các nhiệm vụ ràng buộc CPU
  • Xử lý ngoại lệ nhóm đa bộ xử lý
    • Xử lý ngoại lệ trong khởi tạo công nhân
    • Xử lý ngoại lệ trong thực thi nhiệm vụ
    • Kiểm tra ngoại lệ nhiệm vụ
    • Xử lý ngoại lệ trong các cuộc gọi lại hoàn thành nhiệm vụ
  • Đa bộ xử lý nhóm vs ProcessPoolExecort
    • ProcessPoolExecutor là gì
    • Sự tương đồng giữa Pool và ProcessPoolExecutor
    • Sự khác biệt giữa Pool và ProcessPoolExecutor
    • Tóm tắt sự khác biệt
  • Bộ xử lý đa xử lý thực hành tốt nhất
    • Thực hành 1: Sử dụng Trình quản lý bối cảnh
    • Thực hành 2: Sử dụng bản đồ () cho các vòng lặp song song
    • Thực hành 3: Sử dụng imap_unordered () cho mã đáp ứng
    • Thực hành 4: Sử dụng map_async () để ban hành các nhiệm vụ không đồng bộ
    • Thực hành 5: Sử dụng các chức năng độc lập làm nhiệm vụ
    • Thực hành 6: Sử dụng cho các nhiệm vụ ràng buộc CPU (có thể)
  • Các lỗi phổ biến khi sử dụng nhóm đa xử lý
    • Lỗi 1: Quên __main__
    • Lỗi 2: Sử dụng cuộc gọi chức năng trong application_async ()
    • Lỗi 3: Sử dụng lệnh gọi hàm trong bản đồ ()
    • Lỗi 4: Chữ ký chức năng không chính xác cho MAP ()
    • Lỗi 5: Chữ ký chức năng không chính xác cho cuộc gọi lại
    • Lỗi 6: Đối số hoặc dữ liệu được chia sẻ không hấp dẫn
    • Lỗi 7: Không Flushing in () câu lệnh
  • Những câu hỏi phổ biến khi sử dụng nhóm đa xử lý
    • Làm thế nào để bạn ngừng chạy các nhiệm vụ một cách an toàn?
    • Làm thế nào để giết tất cả các nhiệm vụ?
    • Làm thế nào để bạn chờ đợi tất cả các nhiệm vụ hoàn thành?
    • Làm thế nào để bạn có được kết quả đầu tiên?
    • Làm thế nào để bạn tự động thay đổi số lượng quy trình
    • Làm thế nào để bạn các nhiệm vụ đơn vị và xử lý nhóm?
    • Làm thế nào để bạn so sánh hiệu suất nối tiếp với hiệu suất song song?
    • Làm thế nào để bạn đặt Chunksize trong bản đồ ()?
    • Làm thế nào để bạn gửi một nhiệm vụ tiếp theo?
    • Làm thế nào để bạn thể hiện sự tiến bộ của tất cả các nhiệm vụ?
    • Chúng ta có cần bảo vệ __main__ không?
    • Tôi có cần gọi Freeze_support () không?
    • Làm thế nào để bạn có được một đối tượng không đồng bộ cho các tác vụ được thêm vào bản đồ ()?
    • Làm thế nào để bạn phát hành các nhiệm vụ từ trong các nhiệm vụ?
    • Làm thế nào để bạn sử dụng các nguyên thủy đồng bộ hóa (khóa, semaphore, v.v.) ở công nhân?
  • Phản đối phổ biến đối với việc sử dụng nhóm đa xử lý
    • Điều gì về khóa phiên dịch toàn cầu (GIL)?
    • Có phải các quá trình Python có phải là các quy trình thực sự không?
    • Aren lồng Python Processes Buggy?
    • Có phải là Python Python là một lựa chọn tồi cho sự đồng thời?
    • Tại sao không sử dụng ThreadPool thay thế?
    • Tại sao không sử dụng Multiprocessing.Process thay thế?
    • Tại sao không sử dụng ProcessPoolExecutor thay thế?
    • Tại sao không sử dụng asyncio?
  • Đọc thêm
    • Sách
    • Hướng dẫn liên quan
    • API
    • Người giới thiệu
  • Kết luận

Các quy trình của Python và nhu cầu về các nhóm quy trình

Vì vậy, các quy trình là gì và tại sao chúng ta quan tâm đến nhóm quy trình?

Quá trình Python là gì

Một quy trình đề cập đến một chương trình máy tính.

Mỗi chương trình Python là một quy trình và có một luồng được gọi là luồng chính được sử dụng để thực hiện các hướng dẫn chương trình của bạn. Trên thực tế, mỗi quá trình là một trường hợp của trình thông dịch Python thực thi các hướng dẫn Python (mã byte Python), mức thấp hơn một chút so với mã bạn nhập vào chương trình Python của bạn.

Đôi khi chúng ta có thể cần tạo các quy trình mới để chạy các nhiệm vụ bổ sung đồng thời.

Python cung cấp các quy trình cấp hệ thống thực thông qua lớp quy trình trong mô-đun đa xử lý.Process class in the multiprocessing module.

Hệ điều hành cơ bản kiểm soát các quy trình mới được tạo ra. Trên một số hệ thống, điều đó có thể yêu cầu sinh sản một quy trình mới và trên các hệ thống khác, nó có thể yêu cầu quá trình này được đưa ra. Phương pháp cụ thể hoạt động được sử dụng để tạo các quy trình mới trong Python không phải là điều chúng ta cần phải lo lắng vì nó được quản lý bởi trình thông dịch Python đã cài đặt của bạn.

Một tác vụ có thể được chạy trong một quy trình mới bằng cách tạo một thể hiện của lớp quy trình và chỉ định chức năng để chạy trong quy trình mới thông qua đối số Target Target.Process class and specifying the function to run in the new process via the “target” argument.

.....

# Xác định một tác vụ để chạy trong một quy trình mới

p=Process(target=task)=Process(target=task)

Khi quá trình được tạo, nó phải được bắt đầu bằng cách gọi phương thức start ().start() method.

.....

# Xác định một tác vụ để chạy trong một quy trình mới

p.start().start()

Khi quá trình được tạo, nó phải được bắt đầu bằng cách gọi phương thức start ().

.....

# Xác định một tác vụ để chạy trong một quy trình mới

p.join().join()

Khi quá trình được tạo, nó phải được bắt đầu bằng cách gọi phương thức start ().

# Bắt đầu nhiệm vụ trong một quy trình mới

if__name__=='__main__':__name__=='__main__':

Sau đó, chúng tôi có thể chờ đợi nhiệm vụ hoàn thành bằng cách tham gia quá trình; Ví dụ:

# Đợi nhiệm vụ hoàn thànhProcess to run an ad hoc task function is listed below.

Bất cứ khi nào chúng tôi tạo các quy trình mới, chúng tôi phải bảo vệ điểm nhập của chương trình.

# điểm nhập cho chương trình

# Làm vài thứ...multiprocessing import Process

Kết hợp điều này lại với nhau, ví dụ hoàn chỉnh về việc tạo một quy trình để chạy chức năng tác vụ ad hoc được liệt kê dưới đây.

# SuperfastPython.comtask():

# Ví dụ về việc chạy một chức năng trong một quy trình mớiprint('This is another process', flush=True)

# Bắt đầu nhiệm vụ trong một quy trình mới

if__name__=='__main__':__name__=='__main__':

Sau đó, chúng tôi có thể chờ đợi nhiệm vụ hoàn thành bằng cách tham gia quá trình; Ví dụ:# define a task to run in a new process

    p=Process(target=task)p= Process(target=task)

# Đợi nhiệm vụ hoàn thành# start the task in a new process

    p.start()p.start()

Bất cứ khi nào chúng tôi tạo các quy trình mới, chúng tôi phải bảo vệ điểm nhập của chương trình.# wait for the task to complete

    p.join()p.join()

# điểm nhập cho chương trình

# Làm vài thứ...

Kết hợp điều này lại với nhau, ví dụ hoàn chỉnh về việc tạo một quy trình để chạy chức năng tác vụ ad hoc được liệt kê dưới đây.

# SuperfastPython.com

# Ví dụ về việc chạy một chức năng trong một quy trình mới

Từ quá trình nhập bộ xử lý đa xử lý

# một nhiệm vụ để thực hiện trong một quy trình khác

  • nhiệm vụ def ():
  • & nbsp; & nbsp; & nbsp; & nbsp; in ('Đây là một quy trình khác', flush = true)

& nbsp; & nbsp; & nbsp; & nbsp;# xác định một tác vụ để chạy trong một quy trình mới

& nbsp; & nbsp; & nbsp; & nbsp;# Bắt đầu nhiệm vụ trong một quy trình mớimultiprocessing.Pool class.

& nbsp; & nbsp; & nbsp; & nbsp;# chờ hoàn thành nhiệm vụ

Điều này rất hữu ích để chạy các tác vụ ad hoc một lần trong một quy trình riêng biệt, mặc dù nó trở nên cồng kềnh khi bạn có nhiều nhiệm vụ để chạy.multiprocessing.pool.Pool class provides a process pool in Python.

Mỗi quy trình được tạo ra đòi hỏi phải áp dụng các tài nguyên (ví dụ: một phiên bản của trình thông dịch Python và bộ nhớ cho không gian ngăn xếp chính của quy trình. Chi phí tính toán để thiết lập các quy trình có thể trở nên đắt đỏ nếu chúng ta đang tạo và phá hủy nhiều quy trình nhiều lần cho các nhiệm vụ ad hoc.multiprocessing.pool.Pool class can also be accessed by the alias multiprocessing.Pool. They can be used interchangeably.

Thay vào đó, chúng tôi muốn giữ các quy trình công nhân xung quanh để tái sử dụng nếu chúng tôi mong đợi chạy nhiều nhiệm vụ ad hoc trong suốt chương trình của chúng tôi.

Điều này có thể đạt được bằng cách sử dụng một nhóm quy trình.

Nhóm quy trình là gì

Nhóm quy trình là một mẫu lập trình để tự động quản lý một nhóm các quy trình công nhân.

Nhóm chịu trách nhiệm cho một số lượng cố định các quy trình.

.....

# Xác định một tác vụ để chạy trong một quy trình mới

pool=multiprocessing.pool.Pool(...)=multiprocessing.pool.Pool(...)

Khi quá trình được tạo, nó phải được bắt đầu bằng cách gọi phương thức start ().apply() and map().

Nhóm chịu trách nhiệm cho một số lượng cố định các quy trình.

.....

# Xác định một tác vụ để chạy trong một quy trình mới

results=pool.map(task,items)=pool.map(task,items)

Khi quá trình được tạo, nó phải được bắt đầu bằng cách gọi phương thức start ().

Ví dụ:

.....

# Đóng nhóm quy trình

pool.close().close()

Bây giờ chúng ta có một ý tưởng cấp cao về nhóm Python Process, hãy để Lôi nhìn vào vòng đời của lớp đa xử lý.pool.pool.multiprocessing.pool.Pool class.

Vòng đời của đa bộ xử lý.pool

Đa xử lý.pool cung cấp một nhóm các quy trình công nhân chung.multiprocessing.Pool provides a pool of generic worker processes.

Nó được thiết kế để dễ dàng và đơn giản để sử dụng.

Có bốn bước chính trong vòng đời của việc sử dụng lớp đa xử lý.pool, chúng là: Tạo, gửi, chờ đợi và tắt máy.multiprocessing.Pool class, they are: create, submit, wait, and shutdown.

  1. Tạo: Tạo nhóm quy trình bằng cách gọi đa biến cấu trúc.pool ().: Create the process pool by calling the constructor multiprocessing.Pool().
  2. Gửi: Gửi nhiệm vụ đồng bộ hoặc không đồng bộ.: Submit tasks synchronously or asynchronously.
    1. 2A. Gửi các nhiệm vụ đồng bộ
    2. 2B. Gửi nhiệm vụ không đồng bộ
  3. Đợi: Đợi và nhận kết quả khi các nhiệm vụ hoàn thành (tùy chọn).: Wait and get results as tasks complete (optional).
    1. 3A. Chờ các đối tượng không đồng bộ để hoàn thành
    2. 3B. Chờ các đối tượng không đồng bộ cho kết quả
  4. Tắt máy: Tắt máy xử lý bằng cách gọi Shutdown ().: Shutdown the process pool by calling shutdown().
    1. 4A. Tắt máy tự động với trình quản lý ngữ cảnh

Hình dưới đây giúp hình dung vòng đời của lớp đa xử lý.pool.multiprocessing.Pool class.

Hướng dẫn superfast python multiprocessing - đa xử lý python siêu nhanh
Multiprocessing-Pool-Life-Cycle

Hãy cùng xem xét kỹ hơn về từng bước vòng đời.

Bước 1. Tạo nhóm quy trình

Đầu tiên, một phiên bản đa xử lý.pool phải được tạo.multiprocessing.Pool instance must be created.

Khi một thể hiện của một đa xử lý.pool được tạo, nó có thể được cấu hình.multiprocessing.Pool is created it may be configured.

Nhóm quy trình có thể được cấu hình bằng cách chỉ định các đối số cho hàm tạo lớp đa xử lý.pool.multiprocessing.Pool class constructor.

Các đối số cho hàm tạo như sau:

  • Các quy trình: Số lượng tối đa của các quy trình công nhân để sử dụng trong nhóm.: Maximum number of worker processes to use in the pool.
  • Khởi tạo: Chức năng được thực thi sau mỗi quá trình công nhân được tạo.: Function executed after each worker process is created.
  • initArgs: Đối số cho chức năng khởi tạo quy trình công nhân.: Arguments to the worker process initialization function.
  • MaxTasksperChild: Giới hạn số lượng tác vụ tối đa được thực hiện bởi mỗi quy trình của công nhân.: Limit the maximum number of tasks executed by each worker process.
  • Bối cảnh: Định cấu hình ngữ cảnh đa xử lý như phương thức bắt đầu quá trình.: Configure the multiprocessing context such as the process start method.

Có lẽ đối số quan trọng nhất là các quy trình của người Viking chỉ định số lượng quy trình con công nhân trong nhóm quy trình.processes” that specifies the number of worker child processes in the process pool.

Theo mặc định, Trình xây dựng lớp Multiprocessing.Pool không lấy bất kỳ đối số nào.multiprocessing.Pool class constructor does not take any arguments.

Ví dụ:

.....

# Tạo nhóm quy trình mặc định

pool=multiprocessing.Pool()=multiprocessing.Pool()

Điều này sẽ tạo ra một nhóm quy trình sẽ sử dụng một số quy trình công nhân phù hợp với số lượng lõi CPU logic trong hệ thống của bạn.

Chúng tôi sẽ tìm hiểu thêm về cách định cấu hình nhóm trong các phần sau.

Nếu bạn có thể chờ đợi, bạn có thể tìm hiểu thêm về cách định cấu hình nhóm quy trình trong hướng dẫn:

  • Cách định cấu hình nhóm đa xử lý trong Python

Tiếp theo, hãy để Lôi nhìn vào cách chúng ta có thể phát hành các nhiệm vụ cho nhóm quy trình.

Bước 2. Gửi nhiệm vụ đến nhóm quy trình

Khi đa xử lý.pool đã được tạo, bạn có thể gửi các tác vụ thực thi.multiprocessing.Pool has been created, you can submit tasks execution.

Như đã thảo luận, có hai cách tiếp cận chính để gửi các nhiệm vụ đến nhóm quy trình, chúng là:

  1. Phát hành nhiệm vụ đồng bộ.
  2. Phát hành nhiệm vụ không đồng bộ.

Hãy cùng nhau xem xét kỹ hơn từng cách tiếp cận.

Bước 2A. Phát hành nhiệm vụ đồng bộ

Việc phát hành các nhiệm vụ đồng bộ có nghĩa là người gọi sẽ chặn cho đến khi nhiệm vụ hoặc nhiệm vụ ban hành đã hoàn thành.

Chặn các cuộc gọi đến nhóm quy trình bao gồm Ứng dụng (), map () và starmap ().apply(), map(), and starmap().

Chúng tôi có thể phát hành các tác vụ một lần cho nhóm quy trình bằng hàm application ().apply() function.

Hàm application () lấy tên của hàm để thực hiện theo quy trình công nhân. Cuộc gọi sẽ chặn cho đến khi chức năng được thực thi bởi một quy trình công nhân, sau thời gian đó nó sẽ quay lại.apply() function takes the name of the function to execute by a worker process. The call will block until the function is executed by a worker process, after which time it will return.

Ví dụ:

.....

# Phát hành một nhiệm vụ cho nhóm quy trình

pool.apply(task).apply(task)

Nhóm quy trình cung cấp một phiên bản song song của hàm Bản đồ tích hợp () để phát hành các tác vụ.map() function for issuing tasks.

Ví dụ:

.....

# lặp lại các giá trị trả về từ các tác vụ đã cấp

Forresult Inmap (nhiệm vụ, vật phẩm):result inmap(task,items):

& nbsp; & nbsp; & nbsp; & nbsp;# ...# ...

Hàm starmap () giống như phiên bản song song của hàm map (), ngoại trừ việc nó cho phép mỗi cuộc gọi hàm thực hiện nhiều đối số. Cụ thể, nó có một sự khác biệt trong đó mỗi mục là một đối số có thể lặp lại cho hàm đích.starmap() function is the same as the parallel version of the map() function, except that it allows each function call to take multiple arguments. Specifically, it takes an iterable where each item is an iterable of arguments for the target function.

Ví dụ:

.....

# lặp lại các giá trị trả về từ các tác vụ đã cấp

Forresult Inmap (nhiệm vụ, vật phẩm):result instarmap(task,items):

& nbsp; & nbsp; & nbsp; & nbsp;# ...# ...

Hàm starmap () giống như phiên bản song song của hàm map (), ngoại trừ việc nó cho phép mỗi cuộc gọi hàm thực hiện nhiều đối số. Cụ thể, nó có một sự khác biệt trong đó mỗi mục là một đối số có thể lặp lại cho hàm đích.

Forresult Instarmap (Nhiệm vụ, Mục):

Chúng tôi sẽ xem xét kỹ hơn về cách phát hành các nhiệm vụ trong các phần sau.

Bước 2b. Phát hành nhiệm vụ không đồng bộ

Phát hành các nhiệm vụ không đồng bộ vào nhóm quy trình có nghĩa là người gọi sẽ không chặn, cho phép người gọi tiếp tục với các công việc khác trong khi các tác vụ đang thực hiện.apply_async(), map_async(), and starmap_async().

IMAP () và imap_unordered () rất thú vị. Họ trở lại ngay lập tức, vì vậy họ là các cuộc gọi không chặn kỹ thuật. Các điều có thể được trả lại sẽ mang lại các giá trị trả về khi các tác vụ được hoàn thành. Điều này có nghĩa là đi qua những điều khác nhau sẽ chặn.imap() and imap_unordered() are interesting. They return immediately, so they are technically non-blocking calls. The iterable that is returned will yield return values as tasks are completed. This means traversing the iterable will block.

Application_async (), map_async () và starmap_async () là các phiên bản không đồng bộ của các hàm application (), map () và starmap () được mô tả ở trên.apply_async(), map_async(), and starmap_async() functions are asynchronous versions of the apply(), map(), and starmap() functions described above.

Tất cả đều trả về một đối tượng không đồng bộ ngay lập tức cung cấp một tay cầm về nhiệm vụ hoặc nhiệm vụ đã phát hành.AsyncResult object immediately that provides a handle on the issued task or tasks.

Ví dụ:

.....

# Phát hành các nhiệm vụ cho nhóm quy trình không đồng bộ

result=map_async(task,items)=map_async(task,items)

Hàm IMAP () lấy tên của hàm đích và có thể lặp lại như hàm map ().imap() function takes the name of a target function and an iterable like the map() function.

Sự khác biệt là hàm imap () lười biếng hơn theo hai cách:

  • IMAP () đưa ra nhiều tác vụ cho từng nhóm một, thay vì tất cả cùng một lúc như Map (). issues multiple tasks to the process pool one-by-one, instead of all at once like map().
  • IMAP () trả về một số lượng có thể mang lại kết quả từng người một khi các nhiệm vụ được hoàn thành, thay vì từng người một sau khi tất cả các tác vụ đã hoàn thành như MAP (). returns an iterable that yields results one-by-one as tasks are completed, rather than one-by-one after all tasks have completed like map().

Ví dụ:

.....

# Phát hành các nhiệm vụ cho nhóm quy trình không đồng bộ

Hàm IMAP () lấy tên của hàm đích và có thể lặp lại như hàm map ().result inimap(task,items):

Sự khác biệt là hàm imap () lười biếng hơn theo hai cách:# ...

IMAP () đưa ra nhiều tác vụ cho từng nhóm một, thay vì tất cả cùng một lúc như Map ().imap_unordered() is the same as imap(), except that the returned iterable will yield return values in the order that tasks are completed (e.g. out of order).

Ví dụ:

.....

# Phát hành các nhiệm vụ cho nhóm quy trình không đồng bộ

Hàm IMAP () lấy tên của hàm đích và có thể lặp lại như hàm map ().result inimap_unordered(task,items):

Sự khác biệt là hàm imap () lười biếng hơn theo hai cách:# ...

IMAP () đưa ra nhiều tác vụ cho từng nhóm một, thay vì tất cả cùng một lúc như Map ().

  • IMAP () trả về một số lượng có thể mang lại kết quả từng người một khi các nhiệm vụ được hoàn thành, thay vì từng người một sau khi tất cả các tác vụ đã hoàn thành như MAP ().

# lặp lại kết quả khi các nhiệm vụ được hoàn thành theo thứ tự

Forresult Inimap (Nhiệm vụ, Mục):

& nbsp; & nbsp; & nbsp; & nbsp;# ...AsyncResult object is returned when issuing tasks to multiprocessing.Pool the process pool asynchronously.

IMAP_Unordered () giống như imap (), ngoại trừ việc có thể trả về sẽ mang lại các giá trị trả về theo thứ tự các tác vụ được hoàn thành (ví dụ: không theo thứ tự).

  • # lặp lại kết quả khi các nhiệm vụ được hoàn thành, theo thứ tự chúng được hoàn thành to issue one task.
  • Forresult inimap_unordered (nhiệm vụ, các mục): to issue multiple tasks.
  • Bạn có thể tìm hiểu thêm về cách phát hành các nhiệm vụ cho nhóm quy trình trong hướng dẫn: to issue multiple tasks that take multiple arguments.

Nhóm đa xử lý áp dụng () vs map () vs imap () vs starmap ()AsyncResult provides a handle on one or more issued tasks.

Bây giờ chúng ta đã biết cách phát hành các nhiệm vụ cho nhóm quy trình, hãy để xem xét kỹ hơn việc chờ đợi các nhiệm vụ hoàn thành hoặc nhận kết quả.

Bước 3. Chờ các nhiệm vụ hoàn thành (tùy chọn)AsyncResult, such as if issued tasks do not return values and we are not concerned with when the tasks complete or whether they are completed successfully.

Một đối tượng không đồng bộ được trả về khi ban hành các tác vụ để đa xử lý. Pool nhóm quy trình không đồng bộ.

Điều này có thể đạt được thông qua bất kỳ phương pháp nào sau đây trên nhóm quy trình:AsyncResult to wait, they are:

  • Pool.apply_async () để phát hành một nhiệm vụ.
  • Pool.map_async () để phát hành nhiều nhiệm vụ.

Pool.starmap_async () để phát hành nhiều tác vụ có nhiều đối số.

A Asyncresult cung cấp một tay cầm trên một hoặc nhiều nhiệm vụ được cấp.

Nó cho phép người gọi kiểm tra trạng thái của các nhiệm vụ đã phát hành, chờ hoàn thành các nhiệm vụ và để có được kết quả sau khi hoàn thành các nhiệm vụ.AsyncResult.wait() function.

Chúng tôi không cần sử dụng Asyncresult đã trả lại, chẳng hạn như nếu các nhiệm vụ được phát hành không trả lại giá trị và chúng tôi không quan tâm đến khi các nhiệm vụ hoàn thành hoặc liệu chúng có được hoàn thành thành công hay không.

Ví dụ:

.....

Đó là lý do tại sao bước này trong vòng đời là tùy chọn.

result.wait().wait()

Tuy nhiên, có hai cách chính mà chúng ta có thể sử dụng không đồng bộ để chờ đợi, chúng là:wait() function will return immediately.

Chờ các nhiệm vụ ban hành để hoàn thành.timeout” argument can be specified to set a limit in seconds for how long the caller is willing to wait.

Chờ một kết quả từ các nhiệm vụ đã ban hành.wait() function will return.

Hãy cùng nhau xem xét kỹ hơn từng cách tiếp cận.wait() function does not give an indication that it returned because tasks completed or because the timeout elapsed. Therefore, we can check if the tasks completed via the ready() function.

Ví dụ:

.....

3A. Chờ các đối tượng không đồng bộ để hoàn thành

result.wait(timeout=10).wait(timeout=10)

Chúng ta có thể chờ tất cả các tác vụ hoàn thành thông qua hàm asyncresult.wait ().

ifresult.ready()result.ready()

Điều này sẽ chặn cho đến khi tất cả các nhiệm vụ phát hành được hoàn thành.print('All Done')

    ......

else::

# Chờ nhiệm vụ cấp phát hành để hoàn thànhprint('Not Done Yet')

    ......

Nếu các tác vụ đã hoàn thành, thì hàm Wait () sẽ quay lại ngay lập tức.

Một đối số thời gian chờ của người Viking có thể được chỉ định để đặt giới hạn tính bằng giây trong thời gian người gọi sẵn sàng chờ đợi.AsyncResult.get() function.

Nếu thời gian chờ hết hạn trước khi hoàn thành các tác vụ, hàm chờ () sẽ trở lại.

  • Khi sử dụng thời gian chờ, hàm Wait () không đưa ra dấu hiệu cho thấy nó đã trả lại vì các tác vụ đã hoàn thành hoặc do thời gian chờ đã trôi qua. Do đó, chúng ta có thể kiểm tra xem các tác vụ đã hoàn thành thông qua hàm Sẵn sàng ().: Returns the return value of the target function.
  • # Đợi nhiệm vụ cấp để hoàn thành với thời gian chờ: Returns an iterable over the return values of the target function.
  • # Kiểm tra xem các nhiệm vụ đã hoàn thành: Returns an iterable over the return values of the target function.

Ví dụ:

.....

& nbsp; & nbsp; & nbsp; & nbsp; in ('tất cả đã hoàn thành'))

value=result.get()=result.get()

& nbsp; & nbsp; & nbsp; & nbsp; in ('chưa hoàn thành'))get() will block until the tasks are finished.

3B. Chờ các đối tượng không đồng bộ cho kết quả

Chúng ta có thể nhận được kết quả của một tác vụ được phát hành bằng cách gọi hàm asyncresult.get ().

Một đối số thời gian chờ của người Viking có thể được chỉ định. Nếu các tác vụ vẫn đang chạy và không hoàn thành trong số giây được chỉ định, thì một bộ xử lý.timeout” argument can be specified. If the tasks are still running and do not complete within the specified number of seconds, a multiprocessing.TimeoutError is raised.

Bạn có thể tìm hiểu thêm về đối tượng Asyncresult trong hướng dẫn:

  • Đa bộ xử lý không đồng bộ trong Python

Tiếp theo, hãy để Lôi nhìn vào cách chúng ta có thể tắt nhóm quy trình sau khi chúng ta kết thúc với nó.

Bước 4. Tắt máy quy trình

Đa xử lý.pool có thể được đóng lại khi chúng tôi không có nhiệm vụ nào nữa để phát hành.multiprocessing.Pool can be closed once we have no further tasks to issue.

Có hai cách để tắt nhóm quy trình.

Họ đang:

  • Gọi nhóm.close ().Pool.close().
  • Gọi nhóm.Terminate ().Pool.terminate().

Hàm đóng () sẽ quay lại ngay lập tức và nhóm sẽ không thực hiện bất kỳ nhiệm vụ nào nữa.close() function will return immediately and the pool will not take any further tasks.

Ví dụ:

.....

# Đóng nhóm quy trình

pool.close().close()

Ngoài ra, chúng tôi có thể muốn chấm dứt mạnh mẽ tất cả các quy trình công nhân trẻ em, bất kể họ có thực hiện các nhiệm vụ hay không.

Điều này có thể đạt được thông qua hàm chấm dứt ().terminate() function.

Ví dụ:

.....

# Đóng nhóm quy trình

pool.terminate().terminate()

Ngoài ra, chúng tôi có thể muốn chấm dứt mạnh mẽ tất cả các quy trình công nhân trẻ em, bất kể họ có thực hiện các nhiệm vụ hay không.

Điều này có thể đạt được thông qua hàm chấm dứt ().join() function on the pool.

Ví dụ:

.....

# Đóng nhóm quy trình

pool.join().join()

Ngoài ra, chúng tôi có thể muốn chấm dứt mạnh mẽ tất cả các quy trình công nhân trẻ em, bất kể họ có thực hiện các nhiệm vụ hay không.multiprocessing.Pool in the tutorial:

  • Điều này có thể đạt được thông qua hàm chấm dứt ().

# Đóng mạnh tất cả các quy trình công nhân

Chúng tôi có thể muốn sau đó chờ tất cả các nhiệm vụ trong hồ bơi kết thúc.

Điều này có thể đạt được bằng cách gọi hàm tham gia () trên nhóm.

# Đợi tất cả các nhiệm vụ đã cấp để hoàn thành

Bạn có thể tìm hiểu thêm về việc tắt đa xử lý.pool trong hướng dẫn:

Tắt máy nhân đa xử lý trong Python

Ví dụ:

.....

# Đóng nhóm quy trình

Ngoài ra, chúng tôi có thể muốn chấm dứt mạnh mẽ tất cả các quy trình công nhân trẻ em, bất kể họ có thực hiện các nhiệm vụ hay không.multiprocessing.Pool()aspool:

Điều này có thể đạt được thông qua hàm chấm dứt ().# issue tasks to the pool

# Đóng mạnh tất cả các quy trình công nhân# ...

Chúng tôi có thể muốn sau đó chờ tất cả các nhiệm vụ trong hồ bơi kết thúc.

Điều này có thể đạt được bằng cách gọi hàm tham gia () trên nhóm.

# Đợi tất cả các nhiệm vụ đã cấp để hoàn thànhmultiprocessing.Pool class, we can see that the __exit__() method calls the terminate() method on the process pool when exiting the context manager block.

Bạn có thể tìm hiểu thêm về việc tắt đa xử lý.pool trong hướng dẫn:

Tắt máy nhân đa xử lý trong Pythonmultiprocessing.Pool in the tutorial:

  • Một cách tiếp cận khác là tự động tắt nhóm quy trình với giao diện Trình quản lý ngữ cảnh.

Bước 4A. Trình quản lý bối cảnh nhóm đa xử lý
Download my FREE PDF cheat sheet

Trình quản lý bối cảnh là một giao diện trên các đối tượng Python để xác định bối cảnh chạy mới.

Python cung cấp giao diện Trình quản lý bối cảnh trên nhóm quy trình.multiprocessing.Pool.

Điều này đạt được một kết quả tương tự như sử dụng mẫu thử-ngoại trừ cuối cùng, với ít mã hơn.

Cụ thể, nó giống như một mẫu thử cuối cùng, trong đó mọi xử lý ngoại lệ phải được thêm vào và xảy ra trong chính khối mã.

# Tạo và định cấu hình nhóm quy trình

với đa xử lý.pool () aspool:

& nbsp; & nbsp; & nbsp; & nbsp;# phát hành các nhiệm vụ cho nhóm

& nbsp; & nbsp; & nbsp; & nbsp;# ...

# tự động đóng nhóm

Có một sự khác biệt quan trọng với khối cố gắng.

Nếu chúng ta xem mã nguồn cho lớp đa xử lý.pool, chúng ta có thể thấy rằng phương thức __exit __ () gọi phương thức interpinate () trên nhóm quy trình khi thoát khỏi khối trình quản lý ngữ cảnh.

  • /usr/share/dict/words
  • /usr/dict/words

Điều này có nghĩa là nhóm được đóng mạnh một khi khối trình quản lý bối cảnh bị thoát ra. Nó đảm bảo rằng các tài nguyên của nhóm quy trình được phát hành trước khi tiếp tục, nhưng không đảm bảo rằng các nhiệm vụ đã được phát hành được hoàn thành trước./usr/share/dict/words‘ and contains 235,886 words calculated using the command:

Bạn có thể tìm hiểu thêm về giao diện Trình quản lý ngữ cảnh cho Multiprocessing.Pool trong hướng dẫn:

Trình quản lý bối cảnh nhóm đa xử lý

Bị bối rối bởi API Lớp Pool? Tải xuống bảng cheat pdf miễn phí của tôi

Ví dụ về nhóm đa xử lý

  • Trong phần này, chúng tôi sẽ xem xét một ví dụ đầy đủ hơn về việc sử dụng đa xử lý.pool.

Hãy xem xét một tình huống mà chúng tôi có thể muốn kiểm tra xem một từ có được biết đến chương trình hay không, ví dụ: cho dù đó là trong một từ điển của các từ đã biết.1m_words.txt“.

Nếu từ được biết, đó là tốt, nhưng nếu không, chúng tôi có thể muốn hành động cho người dùng, có lẽ nhấn mạnh nó trong đọc như kiểm tra chính tả tự động.

Một cách tiếp cận để thực hiện tính năng này sẽ là tải một từ điển của các từ đã biết và tạo ra một hàm băm của mỗi từ. Sau đó, chúng ta có thể băm các từ mới và kiểm tra xem chúng có tồn tại trong tập hợp các từ băm đã biết hay không.

Đây là một vấn đề tốt để khám phá với đa xử lý.Pool là các từ băm có thể tương đối chậm, đặc biệt là đối với các từ điển lớn của hàng trăm ngàn hoặc hàng triệu từ đã biết.

Đầu tiên, hãy để phát triển một phiên bản nối tiếp (không hòa âm) của chương trình.

Băm một từ điển của các từ từng người một

Bước đầu tiên là chọn một từ điển của các từ để sử dụng.

Aartjan

aasen

AB

ABACUS

Abadines

Abagael

Abagail

Abahri

Abasolo

Abazari

...

Đầu tiên, chúng ta cần tải danh sách các từ vào bộ nhớ.

Điều này có thể đạt được bằng cách đầu tiên mở tệp, sau đó gọi hàm readlines () sẽ tự động đọc các dòng văn bản ASCII vào một danh sách.readlines() function that will automatically read ASCII lines of text into a list.

Hàm load_words () bên dưới sẽ có một đường dẫn đến tệp văn bản và trả về một danh sách các từ được tải từ tệp.load_words() function below takes a path to the text file and returns a list of words loaded from the file.

# Tải một tệp từ

def load_words (đường dẫn):load_words(path):

& nbsp; & nbsp; & nbsp; & nbsp;# Mở tệp# open the file

& NBSP;with open(path,encoding='utf-8')as file:

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# read all data as lines

        returnfile.readlines()returnfile.readlines()

Tiếp theo, chúng ta cần băm mỗi từ.

Chúng tôi sẽ cố tình chọn hàm băm chậm trong ví dụ này, cụ thể là thuật toán SHA512.

Điều này có sẵn trong Python thông qua hàm Hashlib.Sha512 ().hashlib.sha512() function.

Bạn có thể tìm hiểu thêm về mô -đun Hashlib tại đây:

  • Hashlib - băm an toàn và tiêu hóa tin nhắn

Đầu tiên, chúng ta có thể tạo một thể hiện của đối tượng băm bằng cách gọi hàm sha512 ().sha512() function.

.....

Đầu tiên, chúng ta cần tải danh sách các từ vào bộ nhớ.

hash_object=sha512()=sha512()

Điều này có thể đạt được bằng cách đầu tiên mở tệp, sau đó gọi hàm readlines () sẽ tự động đọc các dòng văn bản ASCII vào một danh sách.

.....

Đầu tiên, chúng ta cần tải danh sách các từ vào bộ nhớ.

byte_data=word.encode('utf-8')=word.encode('utf-8')

Điều này có thể đạt được bằng cách đầu tiên mở tệp, sau đó gọi hàm readlines () sẽ tự động đọc các dòng văn bản ASCII vào một danh sách.

hash_object.update(byte_data).update(byte_data)

Hàm load_words () bên dưới sẽ có một đường dẫn đến tệp văn bản và trả về một danh sách các từ được tải từ tệp.hashlib.hexdigest() function.

.....

Đầu tiên, chúng ta cần tải danh sách các từ vào bộ nhớ.

h=hash_object.hexdigest()=hash_object.hexdigest()

Điều này có thể đạt được bằng cách đầu tiên mở tệp, sau đó gọi hàm readlines () sẽ tự động đọc các dòng văn bản ASCII vào một danh sách.hash_word() function below takes a word and returns a hex hash code of the word.

Hàm load_words () bên dưới sẽ có một đường dẫn đến tệp văn bản và trả về một danh sách các từ được tải từ tệp.

# Tải một tệp từhash_word(word):

def load_words (đường dẫn):# create the hash object

    hash_object=sha512()hash_object=sha512()

& nbsp; & nbsp; & nbsp; & nbsp;# Mở tệp# convert the string to bytes

    byte_data=word.encode('utf-8')byte_data=word.encode('utf-8')

& NBSP;# hash the word

    hash_object.update(byte_data)hash_object.update(byte_data)

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# get the hex hash of the word

    returnhash_object.hexdigest()returnhash_object.hexdigest()

Tiếp theo, chúng ta cần băm mỗi từ.

Chúng tôi sẽ cố tình chọn hàm băm chậm trong ví dụ này, cụ thể là thuật toán SHA512.load_words() then creating a set of hashes of known words by calling our hash_word() for each loaded word.

Điều này có sẵn trong Python thông qua hàm Hashlib.Sha512 ().main() function below implements this.

Bạn có thể tìm hiểu thêm về mô -đun Hashlib tại đây:

Hashlib - băm an toàn và tiêu hóa tin nhắnmain():

Đầu tiên, chúng ta có thể tạo một thể hiện của đối tượng băm bằng cách gọi hàm sha512 ().# load a file of words

    path='1m_words.txt'path='1m_words.txt'

    words=load_words(path)words= load_words(path)

# Tạo đối tượng bămprint(f'Loaded {len(words)} words from {path}')

Tiếp theo, chúng ta có thể chuyển đổi một từ đã cho thành byte và sau đó băm nó bằng hàm băm.# hash all known words

    known_words={hash_word(word)forwordinwords}known_words= {hash_word(word)forwordinwords}

# Chuyển đổi chuỗi thành byteprint(f'Done, with {len(known_words)} hashes')

# băm từ

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

Cuối cùng, chúng ta có thể nhận được một biểu diễn chuỗi hex của băm cho từ bằng cách gọi hàm hashlib.hexdigest ().

# Nhận Hex Hash of the Word

Kết hợp điều này lại với nhau, hàm Hash_word () bên dưới lấy một từ và trả về mã băm hex của từ.hashlib import sha512

Hàm load_words () bên dưới sẽ có một đường dẫn đến tệp văn bản và trả về một danh sách các từ được tải từ tệp.

# Tải một tệp từhash_word(word):

def load_words (đường dẫn):# create the hash object

    hash_object=sha512()hash_object =sha512()

& nbsp; & nbsp; & nbsp; & nbsp;# Mở tệp# convert the string to bytes

    byte_data=word.encode('utf-8')byte_data=word.encode('utf-8')

& NBSP;# hash the word

    hash_object.update(byte_data)hash_object.update(byte_data)

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# get the hex hash of the word

    returnhash_object.hexdigest()returnhash_object.hexdigest()

# Tải một tệp từ

def load_words (đường dẫn):load_words(path):

& nbsp; & nbsp; & nbsp; & nbsp;# Mở tệp# open the file

& NBSP;with open(path,encoding='utf-8')asfile:

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# read all data as lines

        returnfile.readlines()return file.readlines()

Bạn có thể tìm hiểu thêm về mô -đun Hashlib tại đây:

Hashlib - băm an toàn và tiêu hóa tin nhắnmain():

Đầu tiên, chúng ta có thể tạo một thể hiện của đối tượng băm bằng cách gọi hàm sha512 ().# load a file of words

    path='1m_words.txt'path='1m_words.txt'

    words=load_words(path)words =load_words(path)

# Tạo đối tượng bămprint(f'Loaded {len(words)} words from {path}')

Tiếp theo, chúng ta có thể chuyển đổi một từ đã cho thành byte và sau đó băm nó bằng hàm băm.# hash all known words

    known_words={hash_word(word)forwordinwords}known_words= {hash_word(word)forwordinwords}

# Chuyển đổi chuỗi thành byteprint(f'Done, with {len(known_words)} hashes')

if__name__=='__main__':__name__== '__main__':

    main()main()

# băm từ

Cuối cùng, chúng ta có thể nhận được một biểu diễn chuỗi hex của băm cho từ bằng cách gọi hàm hashlib.hexdigest ().

# Nhận Hex Hash of the Word

Kết hợp điều này lại với nhau, hàm Hash_word () bên dưới lấy một từ và trả về mã băm hex của từ.

Ví dụ mất bao lâu để chạy trên hệ thống của bạn? Hãy cho tôi biết trong các ý kiến ​​dưới đây.
Let me know in the comments below.

Đã tải 1049938 từ từ 1m_words.txt

Xong, với băm 979250

Tiếp theo, chúng tôi có thể cập nhật chương trình để băm các từ song song.

Hash một từ điển của các từ đồng thời với bản đồ ()

Các từ băm tương đối chậm, nhưng ngay cả như vậy, băm gần một triệu từ mất dưới hai giây.

Tuy nhiên, chúng ta có thể tăng tốc quá trình bằng cách sử dụng tất cả các CPU trong hệ thống và băm đồng thời các từ.

Điều này có thể đạt được bằng cách sử dụng đa xử lý.pool.multiprocessing.Pool.

Đầu tiên, chúng tôi có thể tạo nhóm quy trình và chỉ định số lượng quy trình đồng thời để chạy. Tôi khuyên bạn nên định cấu hình nhóm để phù hợp với số lượng lõi CPU vật lý trong hệ thống của bạn.

Tôi có bốn lõi, vì vậy ví dụ sẽ sử dụng bốn lõi, nhưng cập nhật nó cho số lượng lõi bạn có sẵn.

.....

# Tạo nhóm quy trình

với Pool (4) Aspool:Pool(4)aspool:

& nbsp; & nbsp; & nbsp; & nbsp;# ...# ...

Tiếp theo, chúng ta cần gửi các nhiệm vụ cho nhóm quy trình, nghĩa là băm của mỗi từ.

Vì nhiệm vụ chỉ đơn giản là áp dụng một hàm cho mỗi mục trong danh sách, chúng ta có thể sử dụng hàm bản đồ () trực tiếp.map() function directly.

Ví dụ:

.....

# Tạo nhóm quy trình

known_words=set(pool.map(hash_word,words))=set(pool.map(hash_word,words))

với Pool (4) Aspool:

& nbsp; & nbsp; & nbsp; & nbsp;# ...main() function to hash words concurrently is listed below.

Tiếp theo, chúng ta cần gửi các nhiệm vụ cho nhóm quy trình, nghĩa là băm của mỗi từ.

Vì nhiệm vụ chỉ đơn giản là áp dụng một hàm cho mỗi mục trong danh sách, chúng ta có thể sử dụng hàm bản đồ () trực tiếp.main():

Ví dụ:# load a file of words

    path='1m_words.txt'path='1m_words.txt'

    words=load_words(path)words= load_words(path)

# Tạo một tập hợp các băm từprint(f'Loaded {len(words)} words from {path}')

Và đó là nó.# create the process pool

Ví dụ: phiên bản cập nhật của hàm Main () thành các từ băm đồng thời được liệt kê bên dưới.with Pool(4)as pool:

# Điểm vào# create a set of word hashes

        known_words=set(pool.map(hash_word,words))known_words=set(pool.map(hash_word,words))

def main ():print(f'Done, with {len(known_words)} hashes')

& nbsp; & nbsp; & nbsp; & nbsp;# tải một tệp từ

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

& nbsp; & nbsp; & nbsp; & nbsp; print (f'loaded {len (từ)} từ từ {path} ')

& nbsp; & nbsp; & nbsp; & nbsp;# tạo nhóm quy trình

& nbsp; & nbsp; & nbsp; & nbsp; với pool (4) aspool:math import ceil

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;hashlib import sha512

& nbsp; & nbsp; & nbsp; & nbsp; print (f'done, với {len (đã biết_ từ)} bămmultiprocessing import Pool

Tying này lại với nhau, ví dụ hoàn chỉnh được liệt kê dưới đây.

# SuperfastPython.comhash_word(word):

# Ví dụ về việc băm một danh sách từ song song với một nhóm quy trình# create the hash object

    hash_object=sha512()hash_object=sha512()

từ trần nhập khẩu toán học# convert the string to bytes

    byte_data=word.encode('utf-8')byte_data =word.encode('utf-8')

Từ Hashlib Nhập khẩu SHA512# hash the word

    hash_object.update(byte_data)hash_object.update(byte_data)

từ nhóm nhập khẩu đa xử lý# get the hex hash of the word

    returnhash_object.hexdigest()return hash_object.hexdigest()

# Hash một từ sử dụng thuật toán SHA

def hash_word (từ):load_words(path):

& nbsp; & nbsp; & nbsp; & nbsp;# tạo đối tượng băm# open the file

& nbsp; & nbsp; & nbsp; & nbsp;# chuyển đổi chuỗi thành bytewith open(path)as file:

& nbsp; & nbsp; & nbsp; & nbsp;# băm từ# read all data as lines

        returnfile.readlines()returnfile.readlines()

Tiếp theo, chúng ta cần gửi các nhiệm vụ cho nhóm quy trình, nghĩa là băm của mỗi từ.

Vì nhiệm vụ chỉ đơn giản là áp dụng một hàm cho mỗi mục trong danh sách, chúng ta có thể sử dụng hàm bản đồ () trực tiếp.main():

Ví dụ:# load a file of words

    path='1m_words.txt'path='1m_words.txt'

    words=load_words(path)words=load_words(path)

# Tạo một tập hợp các băm từprint(f'Loaded {len(words)} words from {path}')

Và đó là nó.# create the process pool

Ví dụ: phiên bản cập nhật của hàm Main () thành các từ băm đồng thời được liệt kê bên dưới.with Pool(4)aspool:

# Điểm vào# create a set of word hashes

        known_words=set(pool.map(hash_word,words))known_words= set(pool.map(hash_word,words))

def main ():print(f'Done, with {len(known_words)} hashes')

if__name__=='__main__':__name__=='__main__':

    main()main()

& nbsp; & nbsp; & nbsp; & nbsp;# tải một tệp từhash_word() function to each word in the loaded list as before, except this time the functions are executed in parallel using the process pool.

& nbsp; & nbsp; & nbsp; & nbsp; print (f'loaded {len (từ)} từ từ {path} ')

& nbsp; & nbsp; & nbsp; & nbsp;# tạo nhóm quy trình

Đã tải 1049938 từ từ 1m_words.txt

Xong, với băm 979250


& nbsp; & nbsp; & nbsp; & nbsp; với pool (4) aspool:

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

& nbsp; & nbsp; & nbsp; & nbsp; print (f'done, với {len (đã biết_ từ)} băm

Tying này lại với nhau, ví dụ hoàn chỉnh được liệt kê dưới đây.
 


# SuperfastPython.com

# Ví dụ về việc băm một danh sách từ song song với một nhóm quy trìnhmultiprocessing.pool.Pool class constructor.

từ trần nhập khẩu toán học

  • Từ Hashlib Nhập khẩu SHA512: Maximum number of worker processes to use in the pool.
  • Khởi tạo: Chức năng được thực thi sau mỗi quá trình công nhân được tạo.: Function executed after each worker process is created.
  • initArgs: Đối số cho chức năng khởi tạo quy trình công nhân.: Arguments to the worker process initialization function.
  • MaxTasksperChild: Giới hạn số lượng tác vụ tối đa được thực hiện bởi mỗi quy trình của công nhân.: Limit the maximum number of tasks executed by each worker process.
  • Bối cảnh: Định cấu hình ngữ cảnh đa xử lý như phương thức bắt đầu quá trình.: Configure the multiprocessing context such as the process start method.

Theo mặc định, Tr trong trình xây dựng lớp Multiprocessing.Pool.Pool không lấy bất kỳ đối số nào.multiprocessing.pool.Pool class constructor does not take any arguments.

Ví dụ:

.....

# Tạo nhóm quy trình mặc định

pool=multiprocessing.pool.Pool()=multiprocessing.pool.Pool()

Điều này sẽ tạo ra một nhóm quy trình sẽ sử dụng một số quy trình công nhân phù hợp với số lượng lõi CPU logic trong hệ thống của bạn.

Nó sẽ không gọi một chức năng khởi tạo các quy trình của công nhân khi chúng được tạo.

Mỗi quy trình của công nhân sẽ có thể thực hiện một số lượng nhiệm vụ không giới hạn trong nhóm.

Cuối cùng, bối cảnh đa xử lý mặc định sẽ được sử dụng, cùng với phương thức bắt đầu hiện được cấu hình hoặc mặc định cho hệ thống.

Bây giờ chúng ta đã biết cấu hình mà nhóm quy trình thực hiện, hãy để xem xét cách chúng ta có thể định cấu hình từng khía cạnh của nhóm quy trình.

Cách định cấu hình số lượng quy trình công nhân

Chúng ta có thể định cấu hình số lượng các quy trình của công nhân trong đa xử lý.pool.pool bằng cách đặt đối số của các quy trình trên mạng trong hàm tạo.multiprocessing.pool.Pool by setting the “processes” argument in the constructor.

Các quy trình là số lượng quy trình công nhân để sử dụng. Nếu các quy trình không có thì số được trả về bởi OS.cpu_count () được sử dụng.

-Đa xử lý-song song dựa trên quy trình

Chúng tôi có thể đặt đối số quy trình của các quy trình trên mạng để chỉ định số lượng quy trình con để tạo và sử dụng làm công nhân trong nhóm quy trình.processes” argument to specify the number of child processes to create and use as workers in the process pool.

Ví dụ:

.....

# Tạo nhóm quy trình mặc định

pool=multiprocessing.pool.Pool(processes=4)=multiprocessing.pool.Pool(processes=4)

Điều này sẽ tạo ra một nhóm quy trình sẽ sử dụng một số quy trình công nhân phù hợp với số lượng lõi CPU logic trong hệ thống của bạn.processes” argument is the first argument in the constructor and does not need to be specified by name to be set, for example:

.....

# Tạo nhóm quy trình mặc định

pool=multiprocessing.pool.Pool(4)=multiprocessing.pool.Pool(4)

Điều này sẽ tạo ra một nhóm quy trình sẽ sử dụng một số quy trình công nhân phù hợp với số lượng lõi CPU logic trong hệ thống của bạn.

Ví dụ:

.....

# Tạo nhóm quy trình mặc định

Điều này sẽ tạo ra một nhóm quy trình sẽ sử dụng một số quy trình công nhân phù hợp với số lượng lõi CPU logic trong hệ thống của bạn.multiprocessing.pool.Pool(4):

Nó sẽ không gọi một chức năng khởi tạo các quy trình của công nhân khi chúng được tạo.# ...

Mỗi quy trình của công nhân sẽ có thể thực hiện một số lượng nhiệm vụ không giới hạn trong nhóm.

  • Cuối cùng, bối cảnh đa xử lý mặc định sẽ được sử dụng, cùng với phương thức bắt đầu hiện được cấu hình hoặc mặc định cho hệ thống.

Bây giờ chúng ta đã biết cấu hình mà nhóm quy trình thực hiện, hãy để xem xét cách chúng ta có thể định cấu hình từng khía cạnh của nhóm quy trình.

Cách định cấu hình số lượng quy trình công nhân

Chúng ta có thể định cấu hình số lượng các quy trình của công nhân trong đa xử lý.pool.pool bằng cách đặt đối số của các quy trình trên mạng trong hàm tạo.

Các quy trình là số lượng quy trình công nhân để sử dụng. Nếu các quy trình không có thì số được trả về bởi OS.cpu_count () được sử dụng.initializer” argument when configuring the process pool via the class constructor.

-Đa xử lý-song song dựa trên quy trìnhinitializer” argument can be set to the name of a function that will be called to initialize the worker processes.

Chúng tôi có thể đặt đối số quy trình của các quy trình trên mạng để chỉ định số lượng quy trình con để tạo và sử dụng làm công nhân trong nhóm quy trình.

-Đa xử lý-song song dựa trên quy trình

Ví dụ:

...

# Tạo nhóm quy trình mặc địnhworker_init():

Nó sẽ không gọi một chức năng khởi tạo các quy trình của công nhân khi chúng được tạo.# ...

.....

# Tạo nhóm quy trình mặc định

pool=multiprocessing.pool.Pool(initializer=worker_init)= multiprocessing.pool.Pool(initializer=worker_init)

Điều này sẽ tạo ra một nhóm quy trình sẽ sử dụng một số quy trình công nhân phù hợp với số lượng lõi CPU logic trong hệ thống của bạn.initargs” argument, which takes an ordered list or tuple of arguments for the custom initialization function.

Ví dụ:

...

# Tạo nhóm quy trình mặc địnhworker_init(arg1,arg2,arg3):

Nó sẽ không gọi một chức năng khởi tạo các quy trình của công nhân khi chúng được tạo.# ...

.....

# Tạo nhóm quy trình mặc định

pool=multiprocessing.pool.Pool(initializer=worker_init,initargs=(arg1,arg2,arg3))= multiprocessing.pool.Pool(initializer=worker_init,initargs=(arg1,arg2,arg3))

Điều này sẽ tạo ra một nhóm quy trình sẽ sử dụng một số quy trình công nhân phù hợp với số lượng lõi CPU logic trong hệ thống của bạn.

  • Nó sẽ không gọi một chức năng khởi tạo các quy trình của công nhân khi chúng được tạo.

Mỗi quy trình của công nhân sẽ có thể thực hiện một số lượng nhiệm vụ không giới hạn trong nhóm.

Cuối cùng, bối cảnh đa xử lý mặc định sẽ được sử dụng, cùng với phương thức bắt đầu hiện được cấu hình hoặc mặc định cho hệ thống.

Bây giờ chúng ta đã biết cấu hình mà nhóm quy trình thực hiện, hãy để xem xét cách chúng ta có thể định cấu hình từng khía cạnh của nhóm quy trình.maxtasksperchild” argument in the multiprocessing.pool.Pool class constructor when configuring a new process pool.

Ví dụ:

.....

# Tạo nhóm quy trình mặc định

pool=multiprocessing.pool.Pool(maxtasksperchild=5)=multiprocessing.pool.Pool(maxtasksperchild=5)

Điều này sẽ tạo ra một nhóm quy trình sẽ sử dụng một số quy trình công nhân phù hợp với số lượng lõi CPU logic trong hệ thống của bạn.

Nó sẽ không gọi một chức năng khởi tạo các quy trình của công nhân khi chúng được tạo.

-Đa xử lý-song song dựa trên quy trình

Theo mặc định, đối số MaxTasksperChild được đặt thành không có, điều đó có nghĩa là mỗi quy trình nhân viên con sẽ chạy trong thời gian sử dụng của nhóm quy trình.

Các MaxTasksperChild mặc định là không có, điều đó có nghĩa là các quy trình của người lao động sẽ sống miễn là nhóm.

-Đa xử lý-song song dựa trên quy trình

Bạn có thể tìm hiểu thêm về việc định cấu hình các tác vụ tối đa cho mỗi quy trình công nhân trong hướng dẫn:

  • Xử lý công việc tối đa của hồ bơi cho mỗi đứa trẻ trong Python

Tiếp theo, hãy để Lôi nhìn vào cách chúng ta có thể định cấu hình bối cảnh đa xử lý cho nhóm.

Cách định cấu hình ngữ cảnh

Chúng ta có thể đặt bối cảnh cho nhóm quy trình thông qua đối số ngữ cảnh của nhóm thành một trình xây dựng lớp đa xử lý.pool.pool.context” argument to the multiprocessing.pool.Pool class constructor.

Bối cảnh có thể được sử dụng để chỉ định bối cảnh được sử dụng để bắt đầu các quy trình của công nhân.

-Đa xử lý-song song dựa trên quy trình

Bối cảnh của người Viking là một thể hiện của bối cảnh đa xử lý được cấu hình bằng phương thức bắt đầu, được tạo thông qua hàm đa biến.get_context ().context” is an instance of a multiprocessing context configured with a start method, created via the multiprocessing.get_context() function.

Theo mặc định, bối cảnh của Nhật Bản là không có, sử dụng bối cảnh mặc định hiện tại và phương thức bắt đầu được cấu hình cho ứng dụng.context” is None, which uses the current default context and start method configured for the application.

Phương pháp bắt đầu là kỹ thuật được sử dụng để bắt đầu các quá trình trẻ em trong Python.

Có ba phương pháp bắt đầu, chúng là:

  • Spawn: Bắt đầu một quá trình Python mới.: start a new Python process.
  • Fork: Sao chép quy trình Python từ một quy trình hiện có.: copy a Python process from an existing process.
  • Forkerver: Quá trình mới mà từ đó các quy trình nĩa trong tương lai sẽ được sao chép.: new process from which future forked processes will be copied.

Bối cảnh đa xử lý cung cấp một cách linh hoạt hơn để quản lý các phương thức bắt đầu quá trình trực tiếp trong một chương trình và có thể là một cách tiếp cận ưa thích để thay đổi các phương thức bắt đầu nói chung, đặc biệt là trong thư viện Python.

Một bối cảnh mới có thể được tạo với một phương thức bắt đầu nhất định và được chuyển đến nhóm quy trình.

Ví dụ:

.....

# Tạo bối cảnh quy trình

ctx=multiprocessing.get_context('fork')=multiprocessing.get_context('fork')

# Tạo một nhóm quy trình với bối cảnh nhất định

pool=multiprocessing.pool.Pool(context=ctx)= multiprocessing.pool.Pool(context=ctx)

Bạn có thể tìm hiểu thêm về việc định cấu hình ngữ cảnh cho nhóm quy trình trong hướng dẫn:

  • Định cấu hình bối cảnh nhóm quy trình

Nhiệm vụ phát hành nhóm đa xử lý

Trong phần này, chúng ta sẽ xem xét kỹ hơn các cách khác nhau mà chúng ta có thể đưa ra các nhiệm vụ cho nhóm đa xử lý.

Bể bơi cung cấp 8 cách để phát hành các nhiệm vụ cho người lao động trong nhóm quy trình.

Họ đang:

  • Pool.apply()
  • Pool.apply_async()
  • Pool.map()
  • Pool.map_async()
  • Pool.imap()
  • Pool.imap_unordered()
  • Pool.starmap()
  • Pool.starmap_async()

Hãy để lần lượt xem xét kỹ hơn và ngắn gọn về từng cách tiếp cận.

Cách sử dụng pool.apply ()

Chúng tôi có thể phát hành các tác vụ một lần cho nhóm quy trình bằng hàm application ().apply() function.

Hàm application () lấy tên của hàm để thực hiện theo quy trình công nhân. Cuộc gọi sẽ chặn cho đến khi chức năng được thực thi bởi một quy trình công nhân, sau thời gian đó nó sẽ quay lại.apply() function takes the name of the function to execute by a worker process. The call will block until the function is executed by a worker process, after which time it will return.

Ví dụ:

.....

# Tạo bối cảnh quy trình

pool.apply(task).apply(task)

# Tạo một nhóm quy trình với bối cảnh nhất địnhPool.apply() function is a parallel version of the now deprecated built-in apply() function.

Bạn có thể tìm hiểu thêm về việc định cấu hình ngữ cảnh cho nhóm quy trình trong hướng dẫn:apply() method are as follows:

  • Định cấu hình bối cảnh nhóm quy trình
  • Nhiệm vụ phát hành nhóm đa xử lý
  • Trong phần này, chúng ta sẽ xem xét kỹ hơn các cách khác nhau mà chúng ta có thể đưa ra các nhiệm vụ cho nhóm đa xử lý.

Bể bơi cung cấp 8 cách để phát hành các nhiệm vụ cho người lao động trong nhóm quy trình.apply() method in the tutorial:

  • Họ đang:

Hãy để lần lượt xem xét kỹ hơn và ngắn gọn về từng cách tiếp cận.

Cách sử dụng pool.apply ()apply_async() function.

Chúng tôi có thể phát hành các tác vụ một lần cho nhóm quy trình bằng hàm application ().

Hàm application () lấy tên của hàm để thực hiện theo quy trình công nhân. Cuộc gọi sẽ chặn cho đến khi chức năng được thực thi bởi một quy trình công nhân, sau thời gian đó nó sẽ quay lại.apply_async() function takes the name of the function to execute in a worker process and returns immediately with a AsyncResult object for the task.

# Phát hành một nhiệm vụ cho nhóm quy trình

Ví dụ:

.....

# Tạo bối cảnh quy trình

result=pool.apply_async(task)=pool.apply_async(task)

# Tạo một nhóm quy trình với bối cảnh nhất định

Ví dụ:

.....

# Tạo bối cảnh quy trình

value=result.get()=result.get()

# Tạo một nhóm quy trình với bối cảnh nhất địnhapply_async() method are as follows:

  • Định cấu hình bối cảnh nhóm quy trình
  • Nhiệm vụ phát hành nhóm đa xử lý
  • Trong phần này, chúng ta sẽ xem xét kỹ hơn các cách khác nhau mà chúng ta có thể đưa ra các nhiệm vụ cho nhóm đa xử lý.AsyncResult.
  • Bể bơi cung cấp 8 cách để phát hành các nhiệm vụ cho người lao động trong nhóm quy trình.

Họ đang:apply_async() method in the tutorial:

  • Hãy để lần lượt xem xét kỹ hơn và ngắn gọn về từng cách tiếp cận.

Cách sử dụng pool.apply ()

Chúng tôi có thể phát hành các tác vụ một lần cho nhóm quy trình bằng hàm application ().map() function for issuing tasks.

Hàm application () lấy tên của hàm để thực hiện theo quy trình công nhân. Cuộc gọi sẽ chặn cho đến khi chức năng được thực thi bởi một quy trình công nhân, sau thời gian đó nó sẽ quay lại.map() function takes the name of a target function and an iterable. A task is created to call the target function for each item in the provided iterable. It returns an iterable over the return values from each call to the target function.

Điều đó có thể đi qua đầu tiên và tất cả các nhiệm vụ được ban hành cùng một lúc. Một đoạn có thể được chỉ định để chia các tác vụ thành các nhóm có thể được gửi đến từng quy trình của công nhân để được thực thi theo đợt.

Ví dụ:

.....

# lặp lại các giá trị trả về từ các tác vụ đã cấp

forresult inpool.map (nhiệm vụ, các mục):result inpool.map(task,items):

& nbsp; & nbsp; & nbsp; & nbsp;# ...# ...

Hàm pool.map () là phiên bản song song của hàm bản đồ tích hợp ().Pool.map() function is a parallel version of the built-in map() function.

Tóm lại, các khả năng của phương thức Bản đồ () như sau:

  • Phát hành nhiều nhiệm vụ cho nhóm quy trình cùng một lúc.
  • Trả về một giá trị hoàn trả.
  • Hỗ trợ một đối số duy nhất cho chức năng đích.
  • Khối cho đến khi tất cả các nhiệm vụ ban hành được hoàn thành.
  • Cho phép các nhiệm vụ được nhóm và thực hiện theo lô của công nhân.

Bạn có thể tìm hiểu thêm về phương thức Bản đồ () trong hướng dẫn:map() method in the tutorial:

  • Nhóm đa xử lý.map () trong Python

Cách sử dụng pool.map_async ()

Nhóm quy trình cung cấp một phiên bản không đồng bộ của hàm Bản đồ tích hợp () để phát hành các tác vụ gọi là MAP_ASYNC ().map() function for issuing tasks called map_async() function.

Hàm map_async () có tên của hàm đích và có thể điều chỉnh được. Một tác vụ được tạo để gọi hàm đích cho từng mục trong ITable được cung cấp. Nó không chặn và trả lại ngay lập tức với một sự bất biến có thể được sử dụng để truy cập vào kết quả.map_async() function takes the name of a target function and an iterable. A task is created to call the target function for each item in the provided iterable. It does not block and returns immediately with an AsyncResult that may be used to access the results.

Điều đó có thể đi qua đầu tiên và tất cả các nhiệm vụ được ban hành cùng một lúc. Một đoạn có thể được chỉ định để chia các tác vụ thành các nhóm có thể được gửi đến từng quy trình của công nhân để được thực thi theo đợt. Nó hỗ trợ chức năng gọi lại cho kết quả và chức năng gọi lại lỗi nếu lỗi được nêu ra.

Ví dụ:

.....

# lặp lại các giá trị trả về từ các tác vụ đã cấp

result=pool.map_async(task,items)=pool.map_async(task,items)

forresult inpool.map (nhiệm vụ, các mục):

Ví dụ:

.....

& nbsp; & nbsp; & nbsp; & nbsp;# ...

Hàm pool.map () là phiên bản song song của hàm bản đồ tích hợp ().value inresult.get():

& nbsp; & nbsp; & nbsp; & nbsp;# ...# ...

Hàm pool.map () là phiên bản song song của hàm bản đồ tích hợp ().map_async() method are as follows:

  • Phát hành nhiều nhiệm vụ cho nhóm quy trình cùng một lúc.
  • Hỗ trợ một đối số duy nhất cho chức năng đích.
  • Khối cho đến khi tất cả các nhiệm vụ ban hành được hoàn thành.AsyncResult for accessing results later.
  • Cho phép các nhiệm vụ được nhóm và thực hiện theo lô của công nhân.
  • Bạn có thể tìm hiểu thêm về phương thức Bản đồ () trong hướng dẫn:

Nhóm đa xử lý.map () trong Pythonmap_async() method in the tutorial:

  • Cách sử dụng pool.map_async ()

Nhóm quy trình cung cấp một phiên bản không đồng bộ của hàm Bản đồ tích hợp () để phát hành các tác vụ gọi là MAP_ASYNC ().

Hàm map_async () có tên của hàm đích và có thể điều chỉnh được. Một tác vụ được tạo để gọi hàm đích cho từng mục trong ITable được cung cấp. Nó không chặn và trả lại ngay lập tức với một sự bất biến có thể được sử dụng để truy cập vào kết quả.imap() function.

Điều đó có thể đi qua đầu tiên và tất cả các nhiệm vụ được ban hành cùng một lúc. Một đoạn có thể được chỉ định để chia các tác vụ thành các nhóm có thể được gửi đến từng quy trình của công nhân để được thực thi theo đợt. Nó hỗ trợ chức năng gọi lại cho kết quả và chức năng gọi lại lỗi nếu lỗi được nêu ra.imap() function takes the name of a target function and an iterable. A task is created to call the target function for each item in the provided iterable.

# Phát hành các nhiệm vụ cho nhóm quy trình không đồng bộ

Sau đó, trạng thái của các tác vụ có thể được kiểm tra và các giá trị trả về từ mỗi cuộc gọi đến hàm đích có thể được lặp lại.imap() function is lazy in that it traverses the provided iterable and issues tasks to the process pool one by one as space becomes available in the process pool. A chunksize can be specified to split the tasks into groups which may be sent to each worker process to be executed in batch.

Ví dụ:

.....

# Lặp lại các giá trị trả về từ các nhiệm vụ đã phát hành

forvalue inresult.get ():result inpool.imap(task,items):

& nbsp; & nbsp; & nbsp; & nbsp;# ...# ...

Hàm pool.map () là phiên bản song song của hàm bản đồ tích hợp ().Pool.imap() function is a parallel version of the now deprecated itertools.imap() function.

Tóm lại, các khả năng của phương thức Bản đồ () như sau:imap() method are as follows:

  • Phát hành nhiều nhiệm vụ cho nhóm quy trình cùng một lúc.
  • Trả về một giá trị hoàn trả.
  • Hỗ trợ một đối số duy nhất cho chức năng đích.
  • Khối cho đến khi tất cả các nhiệm vụ ban hành được hoàn thành.
  • Cho phép các nhiệm vụ được nhóm và thực hiện theo lô của công nhân.

Bạn có thể tìm hiểu thêm về phương thức Bản đồ () trong hướng dẫn:imap() method in the tutorial:

  • Nhóm đa xử lý.map () trong Python

Cách sử dụng pool.map_async ()

Nhóm quy trình cung cấp một phiên bản không đồng bộ của hàm Bản đồ tích hợp () để phát hành các tác vụ gọi là MAP_ASYNC ().imap_unordered() function.

Hàm map_async () có tên của hàm đích và có thể điều chỉnh được. Một tác vụ được tạo để gọi hàm đích cho từng mục trong ITable được cung cấp. Nó không chặn và trả lại ngay lập tức với một sự bất biến có thể được sử dụng để truy cập vào kết quả.imap_unordered() function takes the name of a target function and an iterable. A task is created to call the target function for each item in the provided iterable.

Điều đó có thể đi qua đầu tiên và tất cả các nhiệm vụ được ban hành cùng một lúc. Một đoạn có thể được chỉ định để chia các tác vụ thành các nhóm có thể được gửi đến từng quy trình của công nhân để được thực thi theo đợt. Nó hỗ trợ chức năng gọi lại cho kết quả và chức năng gọi lại lỗi nếu lỗi được nêu ra.

# Phát hành các nhiệm vụ cho nhóm quy trình không đồng bộimap_unordered() function is lazy in that it traverses the provided iterable and issues tasks to the process pool one by one as space becomes available in the process pool. A chunksize can be specified to split the tasks into groups which may be sent to each worker process to be executed in batch.

Ví dụ:

.....

# lặp lại kết quả khi các nhiệm vụ được hoàn thành, theo thứ tự chúng được hoàn thành

forresult inpool.imap_unordered (nhiệm vụ, các mục):result inpool.imap_unordered(task,items):

& nbsp; & nbsp; & nbsp; & nbsp;# ...# ...

Tóm lại, các khả năng của phương thức imap_Unordered () như sau:imap_unordered() method are as follows:

  • Đưa ra nhiều nhiệm vụ cho nhóm quy trình, từng người một.
  • Trả về một giá trị hoàn trả.
  • Hỗ trợ một đối số duy nhất cho chức năng đích.
  • Các khối cho đến khi mỗi nhiệm vụ được hoàn thành theo thứ tự chúng được hoàn thành.
  • Cho phép các nhiệm vụ được nhóm và thực hiện theo lô của công nhân.

Bạn có thể tìm hiểu thêm về phương thức imap_Unordered () trong hướng dẫn:imap_unordered() method in the tutorial:

  • Nhóm đa xử lý.imap_unordered () trong python

Cách sử dụng pool.starmap ()

Chúng tôi có thể phát hành nhiều tác vụ cho nhóm quy trình bằng hàm starmap ().starmap() function.

Hàm starmap () lấy tên của hàm đích và có thể điều chỉnh được. Một tác vụ được tạo để gọi hàm đích cho từng mục trong ITable được cung cấp. Mỗi mục trong ITEBLE có thể là một điều đáng tin cậy, cho phép nhiều đối số được cung cấp cho chức năng đích.starmap() function takes the name of a target function and an iterable. A task is created to call the target function for each item in the provided iterable. Each item in the iterable may itself be an iterable, allowing multiple arguments to be provided to the target function.

Nó trả về một sự lặp lại trên các giá trị trả về từ mỗi cuộc gọi đến hàm đích. Điều đó có thể đi qua đầu tiên và tất cả các nhiệm vụ được ban hành cùng một lúc. Một đoạn có thể được chỉ định để chia các tác vụ thành các nhóm có thể được gửi đến từng quy trình của công nhân để được thực thi theo đợt.

Ví dụ:

.....

# lặp lại kết quả khi các nhiệm vụ được hoàn thành, theo thứ tự chúng được hoàn thành

forresult inpool.imap_unordered (nhiệm vụ, các mục):result inpool.starmap(task,items):

& nbsp; & nbsp; & nbsp; & nbsp;# ...# ...

Tóm lại, các khả năng của phương thức imap_Unordered () như sau:Pool.starmap() function is a parallel version of the itertools.starmap() function.

Đưa ra nhiều nhiệm vụ cho nhóm quy trình, từng người một.starmap() method are as follows:

  • Trả về một giá trị hoàn trả.
  • Trả về một giá trị hoàn trả.
  • Hỗ trợ một đối số duy nhất cho chức năng đích.
  • Các khối cho đến khi mỗi nhiệm vụ được hoàn thành theo thứ tự chúng được hoàn thành.
  • Cho phép các nhiệm vụ được nhóm và thực hiện theo lô của công nhân.

Bạn có thể tìm hiểu thêm về phương thức imap_Unordered () trong hướng dẫn:starmap() method in the tutorial:

  • Nhóm đa xử lý.imap_unordered () trong python

Cách sử dụng pool.starmap ()

Chúng tôi có thể phát hành nhiều tác vụ cho nhóm quy trình bằng hàm starmap ().starmap_async() function.

Hàm starmap () lấy tên của hàm đích và có thể điều chỉnh được. Một tác vụ được tạo để gọi hàm đích cho từng mục trong ITable được cung cấp. Mỗi mục trong ITEBLE có thể là một điều đáng tin cậy, cho phép nhiều đối số được cung cấp cho chức năng đích.starmap_async() function takes the name of a target function and an iterable. A task is created to call the target function for each item in the provided iterable. Each item in the iterable may itself be an iterable, allowing multiple arguments to be provided to the target function.

Nó trả về một sự lặp lại trên các giá trị trả về từ mỗi cuộc gọi đến hàm đích. Điều đó có thể đi qua đầu tiên và tất cả các nhiệm vụ được ban hành cùng một lúc. Một đoạn có thể được chỉ định để chia các tác vụ thành các nhóm có thể được gửi đến từng quy trình của công nhân để được thực thi theo đợt.AsyncResult that may be used to access the results.

# lặp lại các giá trị trả về từ các tác vụ đã cấp

Ví dụ:

.....

Forresult Inpool.Starmap (Nhiệm vụ, Mục):

result=pool.starmap_async(task,items)=pool.starmap_async(task,items)

Hàm pool.starmap () là phiên bản song song của hàm itertools.starmap ().

Ví dụ:

.....

# lặp lại kết quả khi các nhiệm vụ được hoàn thành, theo thứ tự chúng được hoàn thành

forresult inpool.imap_unordered (nhiệm vụ, các mục):value inresult.get():

& nbsp; & nbsp; & nbsp; & nbsp;# ...# ...

Tóm lại, các khả năng của phương thức imap_Unordered () như sau:starmap_async() method are as follows:

  • Trả về một giá trị hoàn trả.
  • Hỗ trợ một đối số duy nhất cho chức năng đích.
  • Các khối cho đến khi mỗi nhiệm vụ được hoàn thành theo thứ tự chúng được hoàn thành.AsyncResult for accessing results later.
  • Cho phép các nhiệm vụ được nhóm và thực hiện theo lô của công nhân.
  • Bạn có thể tìm hiểu thêm về phương thức imap_Unordered () trong hướng dẫn:

Nhóm đa xử lý.imap_unordered () trong pythonstarmap_async() method in the tutorial:

  • Cách sử dụng pool.starmap ()

Chúng tôi có thể phát hành nhiều tác vụ cho nhóm quy trình bằng hàm starmap ().

Hàm starmap () lấy tên của hàm đích và có thể điều chỉnh được. Một tác vụ được tạo để gọi hàm đích cho từng mục trong ITable được cung cấp. Mỗi mục trong ITEBLE có thể là một điều đáng tin cậy, cho phép nhiều đối số được cung cấp cho chức năng đích.

Nó trả về một sự lặp lại trên các giá trị trả về từ mỗi cuộc gọi đến hàm đích. Điều đó có thể đi qua đầu tiên và tất cả các nhiệm vụ được ban hành cùng một lúc. Một đoạn có thể được chỉ định để chia các tác vụ thành các nhóm có thể được gửi đến từng quy trình của công nhân để được thực thi theo đợt.

  • # lặp lại các giá trị trả về từ các tác vụ đã cấp
  • Forresult Inpool.Starmap (Nhiệm vụ, Mục):
  • Hàm pool.starmap () là phiên bản song song của hàm itertools.starmap ().
  • Tóm lại, các khả năng của phương thức starmap () như sau:
  • Phát hành nhiều nhiệm vụ cho nhóm quy trình cùng một lúc.
  • Hỗ trợ nhiều đối số cho chức năng đích.

Khối cho đến khi tất cả các nhiệm vụ ban hành được hoàn thành.

Bạn có thể tìm hiểu thêm về phương thức starmap () trong hướng dẫn:

Hướng dẫn superfast python multiprocessing - đa xử lý python siêu nhanh
Nhóm đa xử lý.starmap () trong python

Cách sử dụng pool.starmap_async ()

  • Nhóm đa xử lý áp dụng () vs map () vs imap () vs starmap ()

Cách sử dụng Asyncresult chi tiết

Một đối tượng đa xử lý.pool.asyncresult được trả về khi phát hành các tác vụ để đa xử lý.pool.pool nhóm quy trình không đồng bộ.multiprocessing.pool.AsyncResult object is returned when issuing tasks to multiprocessing.pool.Pool the process pool asynchronously.

Điều này có thể đạt được thông qua bất kỳ phương pháp nào sau đây trên nhóm quy trình:

  • Pool.apply_async () để phát hành một nhiệm vụ. to issue one task.
  • Pool.map_async () để phát hành nhiều nhiệm vụ. to issue multiple tasks.
  • Pool.starmap_async () để phát hành nhiều tác vụ có nhiều đối số. to issue multiple tasks that take multiple arguments.

Một đối tượng không đồng bộ cung cấp một tay cầm trên một hoặc nhiều tác vụ được cấp.AsyncResult object provides a handle on one or more issued tasks.

Nó cho phép người gọi kiểm tra trạng thái của các nhiệm vụ đã phát hành, chờ hoàn thành các nhiệm vụ và để có được kết quả sau khi hoàn thành các nhiệm vụ.

Làm thế nào để có được một đối tượng không liên quan

Lớp không đồng bộ là đơn giản để sử dụng.AsyncResult class is straightforward to use.

Đầu tiên, bạn phải nhận được một đối tượng Asyncresult bằng cách phát hành một hoặc nhiều tác vụ cho nhóm quy trình bằng bất kỳ hàm application_async (), map_async () hoặc starmap_async ().AsyncResult object by issuing one or more tasks to the process pool using any of the apply_async(), map_async(), or starmap_async() functions.

Ví dụ:

.....

# Phát hành một nhiệm vụ cho nhóm quy trình

result=pool.apply_async(...)=pool.apply_async(...)

Khi bạn có một đối tượng Asyncresult, bạn có thể sử dụng nó để truy vấn trạng thái và nhận kết quả từ nhiệm vụ.AsyncResult object, you can use it to query the status and get results from the task.

Làm thế nào để có được kết quả

Chúng ta có thể nhận được kết quả của một tác vụ được phát hành bằng cách gọi hàm asyncresult.get ().AsyncResult.get() function.

Trả lại kết quả khi nó đến.

-Đa xử lý-song song dựa trên quy trình

Điều này sẽ trả về kết quả của chức năng cụ thể được gọi để phát hành nhiệm vụ.

  • Ứng dụng_async (): Trả về giá trị trả về của hàm đích.: Returns the return value of the target function.
  • MAP_ASYNC (): Trả về một giá trị hoàn trả của hàm mục tiêu.: Returns an iterable over the return values of the target function.
  • starmap_async (): Trả về một số giá trị hoàn trả của chức năng đích.: Returns an iterable over the return values of the target function.

Ví dụ:

.....

# Phát hành một nhiệm vụ cho nhóm quy trình

value=result.get()=result.get()

Khi bạn có một đối tượng Asyncresult, bạn có thể sử dụng nó để truy vấn trạng thái và nhận kết quả từ nhiệm vụ.get() will block until the tasks are finished.

Làm thế nào để có được kết quảtimeout” argument can be specified. If the tasks are still running and do not complete within the specified number of seconds, a multiprocessing.TimeoutError is raised.

Chúng ta có thể nhận được kết quả của một tác vụ được phát hành bằng cách gọi hàm asyncresult.get ().

-Đa xử lý-song song dựa trên quy trình

Ví dụ:

.....

try::

# Phát hành một nhiệm vụ cho nhóm quy trình# get the task result with a timeout

    value=result.get(timeout=10)value=result.get(timeout=10)

Khi bạn có một đối tượng Asyncresult, bạn có thể sử dụng nó để truy vấn trạng thái và nhận kết quả từ nhiệm vụ.multiprocessing.TimeoutError ase:

Làm thế nào để có được kết quả# ...

Chúng ta có thể nhận được kết quả của một tác vụ được phát hành bằng cách gọi hàm asyncresult.get ().

Trả lại kết quả khi nó đến.

-Đa xử lý-song song dựa trên quy trình

Điều này sẽ trả về kết quả của chức năng cụ thể được gọi để phát hành nhiệm vụ.

Ví dụ:

.....

try::

# Phát hành một nhiệm vụ cho nhóm quy trình# get the task result that might raise an exception

    value=result.get()value=result.get()

Khi bạn có một đối tượng Asyncresult, bạn có thể sử dụng nó để truy vấn trạng thái và nhận kết quả từ nhiệm vụ.Exception ase:

Làm thế nào để có được kết quả# ...

Chúng ta có thể nhận được kết quả của một tác vụ được phát hành bằng cách gọi hàm asyncresult.get ().

Trả lại kết quả khi nó đến.AsyncResult.wait() function.

-Đa xử lý-song song dựa trên quy trình

Ví dụ:

.....

# Phát hành một nhiệm vụ cho nhóm quy trình

result.wait().wait()

Khi bạn có một đối tượng Asyncresult, bạn có thể sử dụng nó để truy vấn trạng thái và nhận kết quả từ nhiệm vụ.wait() function will return immediately.

Làm thế nào để có được kết quảtimeout” argument can be specified to set a limit in seconds for how long the caller is willing to wait.

Chúng ta có thể nhận được kết quả của một tác vụ được phát hành bằng cách gọi hàm asyncresult.get ().

Điều này sẽ trả về kết quả của chức năng cụ thể được gọi để phát hành nhiệm vụ.

Ứng dụng_async (): Trả về giá trị trả về của hàm đích.wait() function will return.

MAP_ASYNC (): Trả về một giá trị hoàn trả của hàm mục tiêu.wait() function does not give an indication that it returned because tasks completed or because the timeout elapsed. Therefore, we can check if the tasks completed via the ready() function.

Ví dụ:

.....

# Phát hành một nhiệm vụ cho nhóm quy trình

result.wait(timeout=10).wait(timeout=10)

Khi bạn có một đối tượng Asyncresult, bạn có thể sử dụng nó để truy vấn trạng thái và nhận kết quả từ nhiệm vụ.

ifresult.ready()result.ready()

Làm thế nào để có được kết quảprint('All Done')

    ......

else::

Chúng ta có thể nhận được kết quả của một tác vụ được phát hành bằng cách gọi hàm asyncresult.get ().print('Not Done Yet')

    ......

Trả lại kết quả khi nó đến.

-Đa xử lý-song song dựa trên quy trìnhAsyncResult.ready() function.

Điều này sẽ trả về kết quả của chức năng cụ thể được gọi để phát hành nhiệm vụ.

-Đa xử lý-song song dựa trên quy trình

Điều này sẽ trả về kết quả của chức năng cụ thể được gọi để phát hành nhiệm vụ.True if the tasks have completed, successfully or otherwise, or False if the tasks are still running.

Ví dụ:

.....

# Phát hành một nhiệm vụ cho nhóm quy trình

ifresult.ready():result.ready():

Khi bạn có một đối tượng Asyncresult, bạn có thể sử dụng nó để truy vấn trạng thái và nhận kết quả từ nhiệm vụ.print('Tasks are done')

else::

Làm thế nào để có được kết quảprint('Tasks are not done')

Chúng ta có thể nhận được kết quả của một tác vụ được phát hành bằng cách gọi hàm asyncresult.get ().

Trả lại kết quả khi nó đến.AsyncResult.successful() function.

Các nhiệm vụ được ban hành là thành công nếu không có nhiệm vụ nêu ra một ngoại lệ.

Nếu ít nhất một nhiệm vụ được ban hành đã đưa ra một ngoại lệ, thì cuộc gọi không thành công và hàm thành công () sẽ trả về sai.successful() function will return False.

Hàm này nên được gọi sau khi người ta biết rằng các nhiệm vụ đã hoàn thành, ví dụ: Sẵn sàng () trả về đúng.ready() returns True.

Ví dụ:

.....

# Kiểm tra xem các nhiệm vụ đã hoàn thành

ifresult.ready():result.ready():

& nbsp; & nbsp; & nbsp; & nbsp;# kiểm tra xem các tác vụ có thành công không# check if the tasks were successful

    ifresult.successful():if result.successful():

        print('Successful')print('Successful')

    else:else:

        print('Unsuccessful')print('Unsuccessful')

Nếu các nhiệm vụ được phát hành vẫn đang chạy, một giá trị sẽ được nâng lên.ValueError is raised.

Trả lại liệu cuộc gọi hoàn thành mà không tăng ngoại lệ. Sẽ tăng giá trịerror nếu kết quả chưa sẵn sàng.

-Đa xử lý-song song dựa trên quy trình

Ví dụ:

.....

try::

& nbsp; & nbsp; & nbsp; & nbsp;# kiểm tra xem các tác vụ có thành công không# check if the tasks were successful

    ifresult.successful():ifresult.successful():

        print('Successful')print('Successful')

Nếu các nhiệm vụ được phát hành vẫn đang chạy, một giá trị sẽ được nâng lên.ValueError ase:

Trả lại liệu cuộc gọi hoàn thành mà không tăng ngoại lệ. Sẽ tăng giá trịerror nếu kết quả chưa sẵn sàng.print('Tasks still running')

-Đa xử lý-song song dựa trên quy trìnhAsyncResult object in the tutorial:

  • Ngoại trừ ValueError ASE:

& nbsp; & nbsp; & nbsp; & nbsp; in ('các nhiệm vụ vẫn đang chạy'))

Bạn có thể tìm hiểu thêm về cách sử dụng đối tượng Asyncresult trong hướng dẫn:

Đa bộ xử lý không đồng bộ trong Pythonmultiprocessing.Pool supports custom callback functions.

Tiếp theo, chúng ta hãy xem cách sử dụng các chức năng gọi lại với các tác vụ không đồng bộ.

  1. Các chức năng gọi lại nhóm đa xử lý
  2. Đa xử lý.Pool hỗ trợ các chức năng gọi lại tùy chỉnh.

Các chức năng gọi lại được gọi trong hai tình huống:

Với kết quả của một nhiệm vụ.

Khi một lỗi được nêu ra trong một nhiệm vụ.

  • Hãy cùng nhau xem xét kỹ hơn từng cái.: For issuing a single task asynchronously.
  • Cách định cấu hình chức năng gọi lại: For issuing multiple tasks with a single argument asynchronously.
  • Các cuộc gọi lại kết quả được hỗ trợ trong nhóm quy trình khi phát hành các tác vụ không đồng bộ với bất kỳ chức năng nào sau đây:: For issuing multiple tasks with multiple arguments asynchronously.

Ứng dụng_async (): Để ban hành một nhiệm vụ không đồng bộ.callback” argument.

MAP_ASYNC (): Để phát hành nhiều nhiệm vụ với một đối số không đồng bộ.

Starmap_async (): Để phát hành nhiều nhiệm vụ với nhiều đối số không đồng bộ.None will be passed as an argument to the callback function.

Một cuộc gọi lại kết quả có thể được chỉ định thông qua đối số gọi lại trên mạng.

Đối số chỉ định tên của một hàm tùy chỉnh để gọi với kết quả của tác vụ hoặc tác vụ không đồng bộ.

-Đa xử lý-song song dựa trên quy trình

Ngoại trừ ValueError ASE:apply_async() is configured with a callback, then the callback function will be called with the return value of the task function that was executed.

& nbsp; & nbsp; & nbsp; & nbsp; in ('các nhiệm vụ vẫn đang chạy'))

Bạn có thể tìm hiểu thêm về cách sử dụng đối tượng Asyncresult trong hướng dẫn:result_callback(result):

print(result,flush=True)(result,flush=True)

.....

# Kiểm tra xem các nhiệm vụ đã hoàn thành

result=apply_async(...,callback=result_callback)= apply_async(...,callback=result_callback)

& nbsp; & nbsp; & nbsp; & nbsp;# kiểm tra xem các tác vụ có thành công khôngmap_async() or starmap_async() are configured with a callback, then the callback function will be called with an iterable of return values from all tasks issued to the process pool.

& nbsp; & nbsp; & nbsp; & nbsp; in ('các nhiệm vụ vẫn đang chạy'))

Bạn có thể tìm hiểu thêm về cách sử dụng đối tượng Asyncresult trong hướng dẫn:result_callback(result):

Đa bộ xử lý không đồng bộ trong Python

Tiếp theo, chúng ta hãy xem cách sử dụng các chức năng gọi lại với các tác vụ không đồng bộ.value inresult:

print(value,flush=True)(value, flush=True)

.....

# Kiểm tra xem các nhiệm vụ đã hoàn thành

result=map_async(...,callback=result_callback)=map_async(...,callback=result_callback)

& nbsp; & nbsp; & nbsp; & nbsp;# kiểm tra xem các tác vụ có thành công không

Nếu các nhiệm vụ được phát hành vẫn đang chạy, một giá trị sẽ được nâng lên.

Trả lại liệu cuộc gọi hoàn thành mà không tăng ngoại lệ. Sẽ tăng giá trịerror nếu kết quả chưa sẵn sàng.

-Đa xử lý-song song dựa trên quy trình

Ngoại trừ ValueError ASE:

& nbsp; & nbsp; & nbsp; & nbsp; in ('các nhiệm vụ vẫn đang chạy'))

  • Hãy cùng nhau xem xét kỹ hơn từng cái.: For issuing a single task asynchronously.
  • Cách định cấu hình chức năng gọi lại: For issuing multiple tasks with a single argument asynchronously.
  • Các cuộc gọi lại kết quả được hỗ trợ trong nhóm quy trình khi phát hành các tác vụ không đồng bộ với bất kỳ chức năng nào sau đây:: For issuing multiple tasks with multiple arguments asynchronously.

Ứng dụng_async (): Để ban hành một nhiệm vụ không đồng bộ.error_callback” argument.

MAP_ASYNC (): Để phát hành nhiều nhiệm vụ với một đối số không đồng bộ.

Starmap_async (): Để phát hành nhiều nhiệm vụ với nhiều đối số không đồng bộ.

Một cuộc gọi lại kết quả có thể được chỉ định thông qua đối số gọi lại trên mạng.

Đối số chỉ định tên của một hàm tùy chỉnh để gọi với kết quả của tác vụ hoặc tác vụ không đồng bộ.

-Đa xử lý-song song dựa trên quy trình

Ví dụ: nếu application_async () được cấu hình với một cuộc gọi lại lỗi, thì hàm gọi lại sẽ được gọi với lỗi được nêu trong tác vụ.apply_async() is configured with an error callback, then the callback function will be called with the error raised in the task.

# chức năng gọi lại lỗi

def Custom_callback (lỗi):custom_callback(error):

print(error,flush=True)(error,flush=True)

.....

# Phát hành một nhiệm vụ duy nhất

result=apply_async(...,error_callback=custom_callback)= apply_async(...,error_callback=custom_callback)

Lỗi gọi lại nên được sử dụng để thực hiện hành động nhanh với lỗi được đưa ra bởi một tác vụ trong nhóm quy trình.

Họ không nên chặn hoặc thực hiện trong một thời gian dài vì họ sẽ chiếm các tài nguyên của nhóm quy trình trong khi chạy.

Tiếp theo, hãy để Lôi nhìn vào các mẫu sử dụng phổ biến cho nhóm đa xử lý.

Đa xử lý các mẫu sử dụng phổ biến

Đa xử lý.pool cung cấp rất nhiều tính linh hoạt để thực hiện các nhiệm vụ đồng thời trong Python.multiprocessing.Pool provides a lot of flexibility for executing concurrent tasks in Python.

Tuy nhiên, có một số ít các mẫu sử dụng phổ biến sẽ phù hợp với hầu hết các kịch bản chương trình.

Phần này liệt kê các mẫu sử dụng phổ biến với các ví dụ đã làm việc mà bạn có thể sao chép và dán vào dự án của riêng bạn và thích ứng khi cần thiết.

Các mẫu chúng ta sẽ xem xét như sau:

  • Mẫu 1: Mẫu bản đồ () và lặp lại kết quả
  • Mẫu 2: Ứng dụng_async () và quên mẫu
  • Mẫu 3: map_async () và quên mẫu
  • Mẫu 4: imap_unordered () và sử dụng làm mẫu đã hoàn thành
  • Mẫu 5: imap_unordered () và đợi mẫu đầu tiên

Chúng tôi sẽ sử dụng một nhiệm vụ giả định trong mỗi ví dụ sẽ ngủ trong một khoảng thời gian ngẫu nhiên bằng dưới một giây. Bạn có thể dễ dàng thay thế nhiệm vụ ví dụ này bằng nhiệm vụ của riêng bạn trong mỗi mẫu.

Hãy bắt đầu với mẫu sử dụng đầu tiên.

Mẫu 1: Mẫu bản đồ () và lặp lại kết quả

Mẫu 2: Ứng dụng_async () và quên mẫu

Mẫu 3: map_async () và quên mẫumap() function with the main difference that all function calls are issued to the process pool immediately and we cannot process results until all tasks are completed.

Mẫu 4: imap_unordered () và sử dụng làm mẫu đã hoàn thànhmap() function with our target function and an iterable of arguments and process return values from each function call in a for loop.

.....

# Phát hành một nhiệm vụ duy nhất

Lỗi gọi lại nên được sử dụng để thực hiện hành động nhanh với lỗi được đưa ra bởi một tác vụ trong nhóm quy trình.result inpool.map(task,range(10)):

Họ không nên chặn hoặc thực hiện trong một thời gian dài vì họ sẽ chiếm các tài nguyên của nhóm quy trình trong khi chạy.print(f'>got {result}')

Tiếp theo, hãy để Lôi nhìn vào các mẫu sử dụng phổ biến cho nhóm đa xử lý.map() function on the process pool in the tutorial:

  • Đa xử lý các mẫu sử dụng phổ biến

Đa xử lý.pool cung cấp rất nhiều tính linh hoạt để thực hiện các nhiệm vụ đồng thời trong Python.map() function for the starmap() function.

Tuy nhiên, có một số ít các mẫu sử dụng phổ biến sẽ phù hợp với hầu hết các kịch bản chương trình.starmap() function in the tutorial:

  • Phần này liệt kê các mẫu sử dụng phổ biến với các ví dụ đã làm việc mà bạn có thể sao chép và dán vào dự án của riêng bạn và thích ứng khi cần thiết.

Các mẫu chúng ta sẽ xem xét như sau:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

Mẫu 1: Mẫu bản đồ () và lặp lại kết quả

Mẫu 2: Ứng dụng_async () và quên mẫu

Mẫu 3: map_async () và quên mẫutime import sleep

Mẫu 4: imap_unordered () và sử dụng làm mẫu đã hoàn thànhrandom import random

Mẫu 5: imap_unordered () và đợi mẫu đầu tiênmultiprocessing import Pool

Chúng tôi sẽ sử dụng một nhiệm vụ giả định trong mỗi ví dụ sẽ ngủ trong một khoảng thời gian ngẫu nhiên bằng dưới một giây. Bạn có thể dễ dàng thay thế nhiệm vụ ví dụ này bằng nhiệm vụ của riêng bạn trong mỗi mẫu.

Hãy bắt đầu với mẫu sử dụng đầu tiên.task(value):

Mẫu này liên quan đến việc gọi cùng một chức năng với các đối số khác nhau sau đó lặp lại kết quả.# generate a random value

    random_value=random()random_value=random()

Đây là phiên bản đồng thời và song song của hàm Bản đồ tích hợp () với sự khác biệt chính mà tất cả các cuộc gọi chức năng được phát cho nhóm quy trình ngay lập tức và chúng tôi không thể xử lý kết quả cho đến khi hoàn thành tất cả các tác vụ.# block for moment

    sleep(random_value)sleep(random_value)

Nó yêu cầu chúng tôi gọi hàm map () với hàm mục tiêu của chúng tôi và có thể lặp lại các đối số và xử lý quá trình trả về từ mỗi gọi hàm trong một vòng lặp.# return a value

    return(value,random_value)return(value,random_value)

# Phát hành các nhiệm vụ và kết quả xử lý

if__name__=='__main__':__name__=='__main__':

Forresult inpool.map (Nhiệm vụ, phạm vi (10)):# create the process pool

& nbsp; & nbsp; & nbsp; & nbsp; print (f '> got {result}'))with Pool()aspool:

Bạn có thể tìm hiểu thêm về cách sử dụng hàm map () trên nhóm quy trình trong hướng dẫn:# issue tasks and process results

Nhóm đa xử lý.map () trong Pythonforresult in pool.map(task,range(10)):

Mẫu này có thể được sử dụng cho các hàm đích lấy nhiều đối số bằng cách thay đổi hàm map () cho hàm starmap ().print(f'>got {result}')

Bạn có thể tìm hiểu thêm về hàm starmap () trong hướng dẫn:map() function is called the task() function for each argument in the range 0 to 9.

Nhóm đa xử lý.starmap () trong python

Tying này lại với nhau, ví dụ hoàn chỉnh được liệt kê dưới đây.

# SuperfastPython.com

# Ví dụ về bản đồ một mẫu sử dụng kết quả lặp lại

từ thời gian nhập vào giấc ngủ

từ nhập ngẫu nhiên ngẫu nhiên

từ nhóm nhập khẩu đa xử lý

# Nhiệm vụ thực thi trong một quy trình mới

nhiệm vụ def (giá trị):

& nbsp; & nbsp; & nbsp; & nbsp;# tạo một giá trị ngẫu nhiên

& nbsp; & nbsp; & nbsp; & nbsp;# block cho khoảnh khắc

Mẫu 2: Ứng dụng_async () và quên mẫu

Mẫu 3: map_async () và quên mẫu

Mẫu 4: imap_unordered () và sử dụng làm mẫu đã hoàn thành

Mẫu 5: imap_unordered () và đợi mẫu đầu tiênapply_async() function with the name of the target function and any arguments the target function may take.

Hàm application_async () sẽ trả về một đối tượng không đồng bộ có thể bị bỏ qua.apply_async() function will return an AsyncResult object that can be ignored.

Ví dụ:

.....

# Nhiệm vụ phát hành

_=pool.apply_async(task,args=(1,))=pool.apply_async(task,args=(1,))

Bạn có thể tìm hiểu thêm về hàm application_async () trong hướng dẫn:apply_async() function in the tutorial:

  • Nhóm đa xử lý.apply_async () trong python

Khi tất cả các nhiệm vụ ad hoc đã được ban hành, chúng tôi có thể muốn chờ các nhiệm vụ hoàn thành trước khi đóng nhóm quy trình.

Điều này có thể đạt được bằng cách gọi hàm đóng () trên nhóm để ngăn nó nhận thêm bất kỳ nhiệm vụ nào nữa, sau đó tham gia nhóm để chờ hoàn thành các nhiệm vụ đã phát hành.close() function on the pool to prevent it from receiving any further tasks, then joining the pool to wait for the issued tasks to complete.

.....

# Nhiệm vụ phát hành

pool.close().close()

Bạn có thể tìm hiểu thêm về hàm application_async () trong hướng dẫn:

pool.join().join()

Nhóm đa xử lý.apply_async () trong python

  • Khi tất cả các nhiệm vụ ad hoc đã được ban hành, chúng tôi có thể muốn chờ các nhiệm vụ hoàn thành trước khi đóng nhóm quy trình.

Điều này có thể đạt được bằng cách gọi hàm đóng () trên nhóm để ngăn nó nhận thêm bất kỳ nhiệm vụ nào nữa, sau đó tham gia nhóm để chờ hoàn thành các nhiệm vụ đã phát hành.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

# Đóng hồ bơi

# Đợi tất cả các nhiệm vụ hoàn thành

Bạn có thể tìm hiểu thêm về việc tham gia nhóm quy trình trong hướng dẫn:time import sleep

Tham gia một nhóm đa xử lý trong Pythonrandom import random

Tying này lại với nhau, ví dụ hoàn chỉnh được liệt kê dưới đây.multiprocessing import Pool

# SuperfastPython.com

# Ví dụ về application_async và quên mẫu sử dụngtask(value):

từ thời gian nhập vào giấc ngủ# generate a random value

    random_value=random()random_value=random()

từ nhập ngẫu nhiên ngẫu nhiên# block for moment

    sleep(random_value)sleep(random_value)

từ nhóm nhập khẩu đa xử lý# prepare result

    result=(value,random_value)result=(value,random_value)

# Nhiệm vụ thực thi trong một quy trình mới# report results

nhiệm vụ def (giá trị):print(f'>task got {result}', flush=True)

& nbsp; & nbsp; & nbsp; & nbsp;# tạo một giá trị ngẫu nhiên

if__name__=='__main__':__name__=='__main__':

& nbsp; & nbsp; & nbsp; & nbsp;# block cho khoảnh khắc# create the process pool

& nbsp; & nbsp; & nbsp; & nbsp;# chuẩn bị kết quảwith Pool()as pool:

& nbsp; & nbsp; & nbsp; & nbsp;# Kết quả báo cáo# issue task

        _=pool.apply_async(task,args=(1,))_=pool.apply_async(task,args=(1,))

& nbsp; & nbsp; & nbsp; & nbsp; print (f '> got got {result}', flush = true)# close the pool

        pool.close()pool.close()

# Bảo vệ điểm vào# wait for all tasks to complete

        pool.join()pool.join()

& nbsp; & nbsp; & nbsp; & nbsp;# tạo nhóm quy trình

& nbsp; & nbsp; & nbsp; & nbsp; với pool () aspool:

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;#

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

Chạy ví dụ bắn một nhiệm vụ vào nhóm quy trình và quên nó, cho phép nó hoàn thành trong nền.

Nhiệm vụ được ban hành và quy trình chính là miễn phí để tiếp tục với các phần khác của chương trình.

Trong ví dụ đơn giản này, không có gì khác để tiếp tục, vì vậy quy trình chính sau đó đóng nhóm và chờ tất cả các nhiệm vụ lửa và lửa ad hoc hoàn thành trước khi chấm dứt.

> Nhiệm vụ có (1, 0.1278130542799114)map_async() function that takes the name of the target task and an iterable of arguments for each function call.

Mẫu 3: map_async () và quên mẫuAsyncResult object that provides a handle on the issued tasks, that can be ignored in this case.

Ví dụ:

.....

Mô hình này liên quan đến việc phát hành nhiều nhiệm vụ cho nhóm quy trình và sau đó tiếp tục. Lửa và dữ dội cho nhiều nhiệm vụ.

_=pool.map_async(task,range(10))=pool.map_async(task,range(10))

Điều này rất hữu ích cho việc áp dụng cùng một chức năng cho từng mục trong một mục có thể lặp lại và sau đó không quan tâm đến kết quả hoặc giá trị trả về.map_async() function in the tutorial:

  • Các nhiệm vụ được ban hành không đồng bộ, cho phép người gọi tiếp tục với các phần khác của chương trình.

Điều này có thể đạt được với hàm map_async () có tên của tác vụ mục tiêu và có thể lặp lại các đối số cho mỗi cuộc gọi chức năng.

.....

# Nhiệm vụ phát hành

pool.close().close()

Bạn có thể tìm hiểu thêm về hàm application_async () trong hướng dẫn:

pool.join().join()

Điều này có thể đạt được bằng cách gọi hàm đóng () trên nhóm để ngăn nó nhận thêm bất kỳ nhiệm vụ nào nữa, sau đó tham gia nhóm để chờ hoàn thành các nhiệm vụ đã phát hành.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

# Đóng hồ bơi

# Đợi tất cả các nhiệm vụ hoàn thành

Bạn có thể tìm hiểu thêm về việc tham gia nhóm quy trình trong hướng dẫn:time import sleep

Tham gia một nhóm đa xử lý trong Pythonrandom import random

Tying này lại với nhau, ví dụ hoàn chỉnh được liệt kê dưới đây.multiprocessing import Pool

# SuperfastPython.com

# Ví dụ về application_async và quên mẫu sử dụngtask(value):

từ thời gian nhập vào giấc ngủ# generate a random value

    random_value=random()random_value=random()

từ nhập ngẫu nhiên ngẫu nhiên# block for moment

    sleep(random_value)sleep(random_value)

từ nhóm nhập khẩu đa xử lý# prepare result

    result=(value,random_value)result=(value,random_value)

# Nhiệm vụ thực thi trong một quy trình mới# report results

nhiệm vụ def (giá trị):print(f'>task got {result}', flush=True)

& nbsp; & nbsp; & nbsp; & nbsp;# tạo một giá trị ngẫu nhiên

if__name__=='__main__':__name__=='__main__':

& nbsp; & nbsp; & nbsp; & nbsp;# block cho khoảnh khắc# create the process pool

& nbsp; & nbsp; & nbsp; & nbsp;# chuẩn bị kết quảwith Pool()as pool:

& nbsp; & nbsp; & nbsp; & nbsp;# Kết quả báo cáo# issue tasks to the process pool

        _=pool.map_async(task,range(10))_=pool.map_async(task,range(10))

& nbsp; & nbsp; & nbsp; & nbsp; print (f '> got got {result}', flush = true)# close the pool

        pool.close()pool.close()

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# wait for all tasks to complete

        pool.join()pool.join()

Chạy ví dụ phát hành mười nhiệm vụ cho nhóm quy trình.

Cuộc gọi trả về ngay lập tức và các nhiệm vụ được thực hiện không đồng bộ. Điều này cho phép quá trình chính tiếp tục với các phần khác của chương trình.

Không có gì khác để làm trong ví dụ đơn giản này, vì vậy nhóm quy trình sau đó được đóng lại và các khối quy trình chính, chờ hoàn thành các nhiệm vụ đã phát hành.

> Nhiệm vụ có (1, 0,07000157647675087)

> Nhiệm vụ có (0, 0.23377533908752213)

> Nhiệm vụ có (4, 0.5817185149247178)

> Nhiệm vụ có (3, 0.592827746280798)

> Nhiệm vụ có (9, 0.39735803187389696)

> Nhiệm vụ có (5, 0.6693476274660454)

> Nhiệm vụ có (6, 0.7423437379725698)

> Nhiệm vụ có (7, 0.8881483088702092)

> Nhiệm vụ có (2, 0.9846685764130632)

> Nhiệm vụ có (8, 0.9740735804232945)

Mẫu 4: imap_unordered () và sử dụng làm mẫu đã hoàn thành

Mô hình này là về việc phát hành các nhiệm vụ cho nhóm và sử dụng kết quả cho các nhiệm vụ khi chúng có sẵn.

Điều này có nghĩa là kết quả được nhận ra khỏi trật tự, nếu các nhiệm vụ mất một lượng thời gian thay đổi, thay vì theo thứ tự các nhiệm vụ được cấp cho nhóm quy trình.

Điều này có thể đạt được với hàm imap_unordered (). Nó có một chức năng và có thể lặp lại của các đối số, giống như hàm map ().imap_unordered() function. It takes a function and an iterable of arguments, just like the map() function.

Nó trả về một số lượng có thể mang lại các giá trị trả về từ hàm đích khi các tác vụ được hoàn thành.

Chúng ta có thể gọi hàm imap_unordered () và lặp lại các giá trị trả về trực tiếp trong vòng lặp.imap_unordered() function and iterate the return values directly in a for-loop.

Ví dụ:

.....

# Phát hành các nhiệm vụ và kết quả xử lý

forresult inpool.imap_unordered (nhiệm vụ, phạm vi (10)):result inpool.imap_unordered(task,range(10)):

& nbsp; & nbsp; & nbsp; & nbsp; print (f '> got {result}'))print(f'>got {result}')

Bạn có thể tìm hiểu thêm về hàm imap_unordered () trong hướng dẫn:imap_unordered() function in the tutorial:

  • Nhóm đa xử lý.imap_unordered () trong python

Tying này lại với nhau, ví dụ hoàn chỉnh được liệt kê dưới đây.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

# SuperfastPython.com

# Ví dụ về IMAP_UNORDED và sử dụng làm mẫu sử dụng đã hoàn thành

từ thời gian nhập vào giấc ngủtime import sleep

từ nhập ngẫu nhiên ngẫu nhiênrandom import random

từ nhóm nhập khẩu đa xử lýmultiprocessing import Pool

# Nhiệm vụ thực thi trong một quy trình mới

nhiệm vụ def (giá trị):task(value):

& nbsp; & nbsp; & nbsp; & nbsp;# tạo một giá trị ngẫu nhiên# generate a random value

    random_value=random()random_value=random()

& nbsp; & nbsp; & nbsp; & nbsp;# block cho khoảnh khắc# block for moment

    sleep(random_value)sleep(random_value)

& nbsp; & nbsp; & nbsp; & nbsp;# return kết quả# return result

    return(value,random_value)return(value,random_value)

# Bảo vệ điểm vào

if__name__=='__main__':__name__=='__main__':

& nbsp; & nbsp; & nbsp; & nbsp;# tạo nhóm quy trình# create the process pool

& nbsp; & nbsp; & nbsp; & nbsp; với pool () aspool:with Pool()aspool:

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & NBSP;# issue tasks and process results

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;forresult in pool.imap_unordered(task,range(10)):

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;print(f'>got {result}')

Chạy ví dụ phát hành tất cả các nhiệm vụ cho nhóm, sau đó nhận và xử lý kết quả theo thứ tự các tác vụ được hoàn thành, chứ không phải thứ tự các tác vụ được cấp cho nhóm, ví dụ: không đặt hàng.

> Got (6, 0.27185692519830873)

> Got (7, 0.30517408991009)

> Got (2, 0.4565919197158417)

> Got (0, 0.4866540025699637)

> Got (5, 0,5594145856578583)

> Got (3, 0.6073766993405534)

> Got (1, 0.6665710827894051)

> Got (8, 0.4987608917896833)

> Got (4, 0.8036914328418536)

> Got (9, 0.49972284685751034)

Mẫu 5: imap_unordered () và đợi mẫu đầu tiên

Mô hình này liên quan đến việc phát hành nhiều nhiệm vụ cho nhóm quy trình không đồng bộ, sau đó chờ kết quả đầu tiên hoặc nhiệm vụ đầu tiên hoàn thành.

Đó là một mô hình hữu ích khi có thể có nhiều cách để có được kết quả nhưng chỉ cần một hoặc kết quả đầu tiên là bắt buộc, sau đó, tất cả các nhiệm vụ khác trở nên không liên quan.

Điều này có thể đạt được bằng hàm imap_unordered (), giống như hàm map (), lấy tên của hàm đích và có thể lặp lại các đối số.imap_unordered() function that, like the map() function, takes the name of a target function and an iterable of arguments.

Nó trả về một số lượng có thể mang lại các giá trị trả về theo thứ tự hoàn thành nhiệm vụ.

Điều này có thể đi qua một lần một lần theo cách thủ công thông qua hàm tích hợp tiếp theo () sẽ chỉ quay lại một khi nhiệm vụ đầu tiên hoàn thành lợi nhuận.next() built-in function which will return only once the first task to finish returns.

Ví dụ:

.....

# Phát hành các nhiệm vụ và kết quả xử lý

it=pool.imap_unordered(task,range(10))=pool.imap_unordered(task,range(10))

forresult inpool.imap_unordered (nhiệm vụ, phạm vi (10)):

result=next(it)= next(it)

& nbsp; & nbsp; & nbsp; & nbsp; print (f '> got {result}'))

Tying này lại với nhau, ví dụ hoàn chỉnh được liệt kê dưới đây.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

# SuperfastPython.com

# Ví dụ về IMAP_UNORDED và sử dụng làm mẫu sử dụng đã hoàn thành

từ thời gian nhập vào giấc ngủtime import sleep

từ nhập ngẫu nhiên ngẫu nhiênrandom import random

từ nhóm nhập khẩu đa xử lýmultiprocessing import Pool

# Nhiệm vụ thực thi trong một quy trình mới

nhiệm vụ def (giá trị):task(value):

& nbsp; & nbsp; & nbsp; & nbsp;# tạo một giá trị ngẫu nhiên# generate a random value

    random_value=random()random_value=random()

& nbsp; & nbsp; & nbsp; & nbsp;# block cho khoảnh khắc# block for moment

    sleep(random_value)sleep(random_value)

& nbsp; & nbsp; & nbsp; & nbsp;# return kết quả# return result

    return(value,random_value)return(value,random_value)

# Bảo vệ điểm vào

if__name__=='__main__':__name__=='__main__':

& nbsp; & nbsp; & nbsp; & nbsp;# tạo nhóm quy trình# create the process pool

& nbsp; & nbsp; & nbsp; & nbsp; với pool () aspool:with Pool()aspool:

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & NBSP;# issue tasks and process results

        it=pool.imap_unordered(task,range(10))it= pool.imap_unordered(task,range(10))

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# get the result from the first task to complete

        result=next(it)result= next(it)

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# Báo cáo kết quả đầu tiên# report first result

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;print(f'>got {result}')

Chạy ví dụ đầu tiên phát hành tất cả các nhiệm vụ không đồng bộ.

Kết quả từ nhiệm vụ đầu tiên để hoàn thành sau đó được yêu cầu, chặn cho đến khi có kết quả.

Một nhiệm vụ hoàn thành, trả về một giá trị, sau đó được xử lý, sau đó nhóm quy trình và tất cả các nhiệm vụ còn lại được chấm dứt tự động.

> Got (4, 0.41272860928850164)

Khi nào sử dụng nhóm đa xử lý

Đa xử lý.pool mạnh mẽ và linh hoạt, mặc dù không phù hợp với tất cả các tình huống mà bạn cần chạy một tác vụ nền hoặc áp dụng một hàm cho mỗi mục trong một song song.multiprocessing.Pool is powerful and flexible, although is not suited for all situations where you need to run a background task or apply a function to each item in an iterable in parallel.

Trong phần này, chúng tôi sẽ xem xét một số trường hợp chung mà nó phù hợp, và nơi đó là, sau đó chúng tôi sẽ xem xét các lớp nhiệm vụ rộng và tại sao chúng hoặc không phù hợp với đa xử lý.pool.multiprocessing.Pool.

Sử dụng Multiprocessing.Pool khi

  • Nhiệm vụ của bạn có thể được xác định bởi một chức năng thuần túy không có tác dụng phụ hoặc phụ.
  • Nhiệm vụ của bạn có thể phù hợp với một chức năng Python duy nhất, có khả năng làm cho nó đơn giản và dễ hiểu.
  • Bạn cần thực hiện cùng một nhiệm vụ nhiều lần, ví dụ: Nhiệm vụ đồng nhất.
  • Bạn cần áp dụng cùng một hàm cho mỗi đối tượng trong một bộ sưu tập trong vòng lặp.

Các nhóm xử lý hoạt động tốt nhất khi áp dụng cùng một hàm thuần túy trên một tập hợp các dữ liệu khác nhau (ví dụ: các tác vụ đồng nhất, dữ liệu không đồng nhất). Điều này làm cho mã dễ dàng hơn để đọc và gỡ lỗi. Đây không phải là một quy tắc, chỉ là một gợi ý nhẹ nhàng.

Sử dụng nhiều bộ xử lý.pool khi

  • Bạn cần thực hiện các nhóm các loại nhiệm vụ khác nhau; Một nhóm quá trình có thể được sử dụng cho từng loại nhiệm vụ.
  • Bạn cần thực hiện một đường ống của các nhiệm vụ hoặc hoạt động; Một nhóm quá trình có thể được sử dụng cho mỗi bước.

Các nhóm xử lý có thể hoạt động trên các nhiệm vụ của các loại khác nhau (ví dụ: các nhiệm vụ không đồng nhất), mặc dù nó có thể giúp tổ chức chương trình của bạn và gỡ lỗi dễ dàng nếu một nhóm quy trình riêng biệt chịu trách nhiệm cho từng loại nhiệm vụ. Đây không phải là một quy tắc, chỉ là một gợi ý nhẹ nhàng.

Don Tiết sử dụng đa xử lý.pool khi

  • Bạn có một nhiệm vụ duy nhất; Cân nhắc sử dụng lớp quy trình với đối số của mục tiêu.target” argument.
  • Bạn có các nhiệm vụ chạy dài, chẳng hạn như giám sát hoặc lập lịch; Xem xét mở rộng lớp quy trình.Process class.
  • Các chức năng nhiệm vụ của bạn yêu cầu trạng thái; Xem xét mở rộng lớp quy trình.Process class.
  • Nhiệm vụ của bạn đòi hỏi sự phối hợp; Xem xét sử dụng một quy trình và các mẫu như rào cản hoặc semaphore.Process and patterns like a Barrier or Semaphore.
  • Nhiệm vụ của bạn yêu cầu đồng bộ hóa; Xem xét sử dụng một quy trình và khóa.Process and Locks.
  • Bạn yêu cầu một quá trình kích hoạt trên một sự kiện; Xem xét sử dụng lớp quy trình.Process class.

Điểm ngọt ngào cho các nhóm xử lý là trong việc gửi nhiều nhiệm vụ tương tự, kết quả có thể được sử dụng sau này trong chương trình. Các nhiệm vụ không phù hợp với bản tóm tắt này có lẽ không phù hợp với các nhóm quy trình. Đây không phải là một quy tắc, chỉ là một gợi ý nhẹ nhàng.

Don lồng sử dụng các quy trình cho các nhiệm vụ ràng buộc IO (có thể)

Bạn có thể sử dụng các quy trình cho các tác vụ ràng buộc IO, mặc dù các chủ đề có thể phù hợp hơn.

Nhiệm vụ ràng buộc IO là một loại nhiệm vụ liên quan đến việc đọc từ hoặc ghi vào một thiết bị, tệp hoặc kết nối ổ cắm.

Các hoạt động liên quan đến đầu vào và đầu ra (IO) và tốc độ của các hoạt động này bị ràng buộc bởi thiết bị, ổ cứng hoặc kết nối mạng. Đây là lý do tại sao các nhiệm vụ này được gọi là giới hạn IO.

CPU thực sự nhanh. CPU hiện đại như 4GHz có thể thực hiện 4 tỷ hướng dẫn mỗi giây và bạn có thể có nhiều hơn một CPU trong hệ thống của mình.

Làm IO rất chậm so với tốc độ của CPU.

Tương tác với các thiết bị, đọc và ghi các tệp và kết nối ổ cắm liên quan đến việc gọi hướng dẫn trong hệ điều hành của bạn (kernel), sẽ chờ hoàn thành thao tác. Nếu hoạt động này là trọng tâm chính cho CPU của bạn, chẳng hạn như thực hiện trong chuỗi chính của chương trình Python của bạn, thì CPU của bạn sẽ chờ nhiều mili giây hoặc thậm chí nhiều giây không làm gì cả.

Đó là có khả năng hàng tỷ hoạt động mà nó được ngăn chặn thực thi.

Chúng tôi có thể giải phóng CPU khỏi các hoạt động ràng buộc IO bằng cách thực hiện các hoạt động ràng buộc IO trên một quy trình thực thi khác. Điều này cho phép CPU bắt đầu nhiệm vụ và chuyển nó cho hệ điều hành (kernel) để chờ đợi và giải phóng nó để thực hiện trong một quy trình ứng dụng khác.

Có nhiều hơn nữa cho nó dưới vỏ bọc, nhưng đây là ý chính.

Do đó, các tác vụ chúng tôi thực thi với một đa xử lý.pool có thể là các nhiệm vụ liên quan đến các hoạt động IO.multiprocessing.Pool can be tasks that involve IO operations.

Những ví dụ bao gồm:

  • Đọc hoặc viết một tập tin từ ổ cứng.
  • Đọc hoặc ghi vào đầu ra tiêu chuẩn, đầu vào hoặc lỗi (stdin, stdout, stderr).
  • In một tài liệu.
  • Tải xuống hoặc tải lên một tập tin.
  • Truy vấn một máy chủ.
  • Truy vấn một cơ sở dữ liệu.
  • Chụp ảnh hoặc ghi video.
  • Và nhiều hơn nữa.

Sử dụng các quy trình cho các nhiệm vụ ràng buộc CPU

Bạn có thể nên sử dụng các quy trình cho các nhiệm vụ liên kết CPU.

Nhiệm vụ ràng buộc CPU là một loại nhiệm vụ liên quan đến việc thực hiện tính toán và không liên quan đến IO.

Các hoạt động chỉ liên quan đến dữ liệu trong bộ nhớ chính (RAM) hoặc bộ đệm (bộ đệm CPU) và thực hiện các tính toán trên hoặc với dữ liệu đó. Như vậy, giới hạn về các hoạt động này là tốc độ của CPU. Đây là lý do tại sao chúng tôi gọi chúng là các nhiệm vụ ràng buộc CPU.

Những ví dụ bao gồm:

  • Đọc hoặc viết một tập tin từ ổ cứng.
  • Đọc hoặc ghi vào đầu ra tiêu chuẩn, đầu vào hoặc lỗi (stdin, stdout, stderr).
  • In một tài liệu.
  • Tải xuống hoặc tải lên một tập tin.
  • Truy vấn một máy chủ.
  • Truy vấn một cơ sở dữ liệu.

Chụp ảnh hoặc ghi video.

Và nhiều hơn nữa.multiprocessing.Pool class in Python is probably the best path toward achieving this end.

Sử dụng các quy trình cho các nhiệm vụ ràng buộc CPU

Bạn có thể nên sử dụng các quy trình cho các nhiệm vụ liên kết CPU.

Nhiệm vụ ràng buộc CPU là một loại nhiệm vụ liên quan đến việc thực hiện tính toán và không liên quan đến IO.

Các hoạt động chỉ liên quan đến dữ liệu trong bộ nhớ chính (RAM) hoặc bộ đệm (bộ đệm CPU) và thực hiện các tính toán trên hoặc với dữ liệu đó. Như vậy, giới hạn về các hoạt động này là tốc độ của CPU. Đây là lý do tại sao chúng tôi gọi chúng là các nhiệm vụ ràng buộc CPU.

Tính toán điểm trong một fractal.

  1. Ước tính PI
  2. Bao thanh toán số nguyên tố.
  3. Phân tích cú pháp HTML, JSON, vv Tài liệu.

Xử lý văn bản.

Chạy mô phỏng.

CPU rất nhanh và chúng tôi thường có nhiều hơn một CPU. Chúng tôi muốn thực hiện các nhiệm vụ của mình và sử dụng đầy đủ nhiều lõi CPU trong phần cứng hiện đại.

Sử dụng các quy trình và nhóm xử lý thông qua lớp đa xử lý.pool trong Python có lẽ là con đường tốt nhất để đạt được kết thúc này.initializer” argument to specify the function name and “initargs” to specify a tuple of arguments to the function.

Xử lý ngoại lệ nhóm đa bộ xử lý

Xử lý ngoại lệ là một cân nhắc quan trọng khi sử dụng các quy trình.

Mã có thể nêu ra một ngoại lệ khi có điều gì đó bất ngờ xảy ra và ngoại lệ nên được xử lý rõ ràng bởi ứng dụng của bạn, ngay cả khi nó có nghĩa là đăng nhập và tiếp tục.

Các quy trình Python rất phù hợp để sử dụng với các tác vụ gắn IO và các hoạt động trong các tác vụ này thường tăng các ngoại lệ, chẳng hạn như nếu không thể đạt được máy chủ, nếu mạng đi xuống, nếu không thể tìm thấy tệp, v.v.worker_init():

Có ba điểm bạn có thể cần xem xét xử lý ngoại lệ khi sử dụng đa xử lý.pool.pool, chúng là:# ...

Quá trình khởi tạo..

Thực thi nhiệm vụ

pool=multiprocessing.pool.Pool(initializer=worker_init)= multiprocessing.pool.Pool(initializer=worker_init)

Nhiệm vụ hoàn thành cuộc gọi lại

  • Hãy lần lượt xem xét kỹ hơn từng điểm.

Xử lý ngoại lệ trong khởi tạo công nhân

Bạn có thể chỉ định chức năng khởi tạo tùy chỉnh khi định cấu hình Multiprocessing.Pool.Pool.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

Điều này có thể được đặt thông qua đối số của bộ khởi tạo trên mạng để chỉ định tên chức năng và các bộ khởi động, để chỉ định một phần của các đối số cho hàm.

Mỗi quá trình bắt đầu bởi nhóm quy trình sẽ gọi chức năng khởi tạo của bạn trước khi bắt đầu quá trình.

Ví dụ:time import sleep

# chức năng khởi tạo quy trình công nhânmultiprocessing.pool import Pool

def worker_init ():

& nbsp; & nbsp; & nbsp; & nbsp;# ...init():

...# raise an exception

# Tạo một nhóm quy trình và khởi tạo công nhânraise Exception('Something bad happened!')

Bạn có thể tìm hiểu thêm về việc định cấu hình nhóm với các chức năng khởi tạo công nhân trong hướng dẫn:

Bộ khởi tạo nhóm đa xử lý trong Pythontask():

Nếu chức năng khởi tạo của bạn làm tăng một ngoại lệ, nó sẽ phá vỡ nhóm quy trình của bạn.# block for a moment

    sleep(1)sleep(1)

Chúng ta có thể chứng minh điều này với một ví dụ về chức năng khởi tạo giả tạo làm tăng một ngoại lệ.

if__name__=='__main__':__name__=='__main__':

# SuperfastPython.com# create a process pool

# Ví dụ về một ngoại lệ được nêu trong chức năng khởi tạo công nhânwith Pool(initializer=init)aspool:

từ thời gian nhập vào giấc ngủ# issue a task

        pool.apply(task)pool.apply(task)

từ đa bộ xử lý.pool Pool

# chức năng để khởi tạo quy trình công nhân

def init ():

& nbsp; & nbsp; & nbsp; & nbsp;# nâng cao một ngoại lệ

& nbsp; & nbsp; & nbsp; & nbsp; nâng cao ngoại lệ ('một cái gì đó xấu đã xảy ra!')

Một ví dụ bị cắt ngắn của đầu ra được liệt kê dưới đây.

Quy trình SpawnPoolWorker-1:

Traceback (cuộc gọi gần đây nhất cuối cùng):

...

Nâng cao ngoại lệ ('Một cái gì đó xấu đã xảy ra!')

Ngoại lệ: Một cái gì đó xấu đã xảy ra!

...

Nâng cao ngoại lệ ('Một cái gì đó xấu đã xảy ra!')

Ngoại lệ: Một cái gì đó xấu đã xảy ra!

Điều này nhấn mạnh rằng nếu bạn sử dụng chức năng khởi tạo tùy chỉnh, bạn phải xem xét cẩn thận các ngoại lệ có thể được nêu ra và có thể xử lý chúng, nếu không có nguy cơ tất cả các nhiệm vụ phụ thuộc vào nhóm quy trình.

Xử lý ngoại lệ trong thực thi nhiệm vụ

Một ngoại lệ có thể xảy ra trong khi thực hiện nhiệm vụ của bạn.apply(), map(), or starmap() the exception will be re-raised in the caller.

Điều này sẽ khiến nhiệm vụ ngừng thực hiện, nhưng sẽ không phá vỡ nhóm quy trình.apply_async(), map_async(), or starmap_async(), an AsyncResult object will be returned. If a task issued asynchronously raises an exception, it will be caught by the process pool and re-raised if you call get() function in the AsyncResult object in order to get the result.

Nếu các tác vụ được phát hành với hàm đồng bộ, chẳng hạn như Ứng dụng (), map () hoặc starmap (), ngoại lệ sẽ được nêu lại trong người gọi.

  1. Nếu các tác vụ được phát hành với hàm không đồng bộ như application_async (), map_async () hoặc starmap_async (), một đối tượng không đồng bộ sẽ được trả về. Nếu một nhiệm vụ được phát hành không đồng bộ một ngoại lệ, nó sẽ bị nhóm xử lý bắt gặp và được nêu lại nếu bạn gọi chức năng GET () trong đối tượng Asyncresult để có được kết quả.
  2. Điều đó có nghĩa là bạn có hai tùy chọn để xử lý các ngoại lệ trong các nhiệm vụ, chúng là:

Xử lý các ngoại lệ trong chức năng nhiệm vụ.

Xử lý các trường hợp ngoại lệ khi nhận được kết quả từ các nhiệm vụ.

Hãy cùng nhau xem xét kỹ hơn từng cách tiếp cận.

Xử lý ngoại lệ trong nhiệm vụNone.

Xử lý ngoại lệ trong nhiệm vụ có nghĩa là bạn cần một số cơ chế để cho người nhận kết quả biết rằng điều gì đó bất ngờ đã xảy ra.

Điều này có thể thông qua giá trị trả về từ hàm, ví dụ: Không có.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

Ngoài ra, bạn có thể tái lập một ngoại lệ và có người nhận xử lý trực tiếp. Tùy chọn thứ ba có thể là sử dụng một số trạng thái rộng hơn hoặc trạng thái toàn cầu hơn, có lẽ được truyền bằng cách tham chiếu vào cuộc gọi đến chức năng.

Ví dụ dưới đây xác định một nhiệm vụ công việc sẽ tăng một ngoại lệ, nhưng sẽ bắt được ngoại lệ và trả về kết quả cho thấy trường hợp thất bại.

# SuperfastPython.comtime import sleep

# Ví dụ về việc xử lý một ngoại lệ được nêu trong một nhiệm vụmultiprocessing.pool import Pool

từ thời gian nhập vào giấc ngủ

từ đa bộ xử lý.pool Pooltask():

# Nhiệm vụ được thực hiện trong một quy trình công nhân# block for a moment

    sleep(1)sleep(1)

    try:try:

nhiệm vụ def ():raise Exception('Something bad happened!')

& nbsp; & nbsp; & nbsp; & nbsp;# block trong giây látexcept Exception:

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;return 'Unable to get the result'

& nbsp; & nbsp; & nbsp; & nbsp; ngoại trừ ngoại lệ:return'Never gets here'

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

if__name__=='__main__':__name__=='__main__':

& nbsp; & nbsp;# create a process pool

# Bảo vệ điểm vàowith Pool()aspool:

& nbsp; & nbsp; & nbsp; & nbsp;# tạo một nhóm quy trình# issue a task

        result=pool.apply_async(task)result=pool.apply_async(task)

& nbsp; & nbsp; & nbsp; & nbsp; với pool () aspool:# get the result

        value=result.get()value=result.get()

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;## report the result

        print(value)print(value)

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# Nhận kết quả

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# báo cáo kết quả

Chạy ví dụ bắt đầu nhóm quy trình theo bình thường, phát hành nhiệm vụ, sau đó chặn chờ kết quả.apply(), apply_async() and map().

Nhiệm vụ làm tăng một ngoại lệ và kết quả nhận được là một thông báo lỗi.

Cách tiếp cận này được làm sạch hợp lý cho mã người nhận và sẽ phù hợp với các tác vụ được ban hành bởi cả hai hàm đồng bộ và không đồng bộ như application (), application_async () và map ().

Nó có thể yêu cầu xử lý đặc biệt giá trị trả lại tùy chỉnh cho trường hợp thất bại.

Xử lý ngoại lệ bên ngoài nhiệm vụ

Một giải pháp thay thế để xử lý ngoại lệ trong nhiệm vụ là để lại trách nhiệm cho người nhận kết quả.

Điều này có thể cảm thấy giống như một giải pháp tự nhiên hơn, vì nó phù hợp với phiên bản đồng bộ của cùng một hoạt động, ví dụ: Nếu chúng tôi thực hiện cuộc gọi chức năng trong vòng lặp.Exception, which is then handled by the recipient when issuing the task asynchronously and then attempting to get the result from the returned AsyncResult object.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

Ngoài ra, bạn có thể tái lập một ngoại lệ và có người nhận xử lý trực tiếp. Tùy chọn thứ ba có thể là sử dụng một số trạng thái rộng hơn hoặc trạng thái toàn cầu hơn, có lẽ được truyền bằng cách tham chiếu vào cuộc gọi đến chức năng.

Ví dụ dưới đây xác định một nhiệm vụ công việc sẽ tăng một ngoại lệ, nhưng sẽ bắt được ngoại lệ và trả về kết quả cho thấy trường hợp thất bại.

# SuperfastPython.comtime import sleep

# Ví dụ về việc xử lý một ngoại lệ được nêu trong một nhiệm vụmultiprocessing.pool import Pool

từ thời gian nhập vào giấc ngủ

từ đa bộ xử lý.pool Pooltask():

# Nhiệm vụ được thực hiện trong một quy trình công nhân# block for a moment

    sleep(1)sleep(1)

nhiệm vụ def ():# fail with an exception

& nbsp; & nbsp; & nbsp; & nbsp;# block trong giây látraise Exception('Something bad happened!')

& nbsp; & nbsp; & nbsp; & nbsp;# giá trị trả về không thể truy cập# unreachable return value

& nbsp; & nbsp;return 'Never gets here'

# Bảo vệ điểm vào

if__name__=='__main__':__name__=='__main__':

& nbsp; & nbsp; & nbsp; & nbsp;# tạo một nhóm quy trình# create a process pool

& nbsp; & nbsp; & nbsp; & nbsp; với pool () aspool:with Pool()aspool:

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;## issue a task

        result=pool.apply_async(task)result=pool.apply_async(task)

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# Nhận kết quả# get the result

        try:try:

            value=result.get()value =result.get()

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# report the result

            print(value)print(value)

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; trừ ngoại lệ:except Exception:

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;print('Unable to get the result')

Chạy ví dụ tạo ra nhóm quy trình và gửi công việc theo bình thường.

Nhiệm vụ không thành công với một ngoại lệ, nhóm quy trình bắt được ngoại lệ, lưu trữ nó, sau đó tự nâng nó khi chúng ta gọi hàm get () trong đối tượng Asyncresult.get() function in the AsyncResult object.

Người nhận kết quả chấp nhận ngoại lệ và bắt nó, báo cáo một trường hợp thất bại.

Cách tiếp cận này cũng sẽ hoạt động cho bất kỳ nhiệm vụ nào được ban hành đồng bộ vào nhóm quy trình.

Trong trường hợp này, ngoại lệ được đưa ra bởi nhiệm vụ được bắt bởi nhóm quy trình và được tăng lại trong người gọi khi nhận được kết quả.

Ví dụ dưới đây cho thấy việc xử lý một ngoại lệ trong người gọi cho một nhiệm vụ được ban hành đồng bộ.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

# SuperfastPython.com

# Ví dụ về việc xử lý một ngoại lệ được nêu trong một nhiệm vụ trong người gọi

từ thời gian nhập vào giấc ngủtime import sleep

từ đa bộ xử lý.pool Poolmultiprocessing.pool import Pool

# Nhiệm vụ được thực hiện trong một quy trình công nhân

nhiệm vụ def ():task():

& nbsp; & nbsp; & nbsp; & nbsp;# block trong giây lát# block for a moment

    sleep(1)sleep(1)

& nbsp; & nbsp; & nbsp; & nbsp;# thất bại với một ngoại lệ# fail with an exception

& nbsp; & nbsp; & nbsp; & nbsp; nâng cao ngoại lệ ('một cái gì đó xấu đã xảy ra!')raise Exception('Something bad happened!')

& nbsp; & nbsp; & nbsp; & nbsp;# giá trị trả về không thể truy cập# unreachable return value

& nbsp; & nbsp;return 'Never gets here'

# Bảo vệ điểm vào

if__name__=='__main__':__name__=='__main__':

& nbsp; & nbsp; & nbsp; & nbsp;# tạo một nhóm quy trình# create a process pool

& nbsp; & nbsp; & nbsp; & nbsp; với pool () aspool:with Pool()aspool:

        try:try:

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;## issue a task and get the result

            value=pool.apply(task)value=pool.apply(task)

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# report the result

            print(value)print(value)

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; trừ ngoại lệ:except Exception:

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;print('Unable to get the result')

Chạy ví dụ tạo ra nhóm quy trình và gửi công việc theo bình thường.

Nhiệm vụ không thành công với một ngoại lệ, nhóm quy trình bắt được ngoại lệ, lưu trữ nó, sau đó tự nâng nó khi chúng ta gọi hàm get () trong đối tượng Asyncresult.

Người nhận kết quả chấp nhận ngoại lệ và bắt nó, báo cáo một trường hợp thất bại.

Cách tiếp cận này cũng sẽ hoạt động cho bất kỳ nhiệm vụ nào được ban hành đồng bộ vào nhóm quy trình.

Trong trường hợp này, ngoại lệ được đưa ra bởi nhiệm vụ được bắt bởi nhóm quy trình và được tăng lại trong người gọi khi nhận được kết quả.successful() function on the AsyncResult object for tasks issued asynchronously to the process pool.

Ví dụ dưới đây cho thấy việc xử lý một ngoại lệ trong người gọi cho một nhiệm vụ được ban hành đồng bộ.True) or whether it failed with an Exception or similar (False).

# SuperfastPython.com

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

# SuperfastPython.com

# Ví dụ về việc xử lý một ngoại lệ được nêu trong một nhiệm vụ trong người gọi

từ thời gian nhập vào giấc ngủtime import sleep

từ đa bộ xử lý.pool Poolmultiprocessing.pool import Pool

# Nhiệm vụ được thực hiện trong một quy trình công nhân

nhiệm vụ def ():task():

& nbsp; & nbsp; & nbsp; & nbsp;# block trong giây lát# block for a moment

    sleep(1)sleep(1)

& nbsp; & nbsp; & nbsp; & nbsp;# thất bại với một ngoại lệ# fail with an exception

& nbsp; & nbsp; & nbsp; & nbsp; nâng cao ngoại lệ ('một cái gì đó xấu đã xảy ra!')raise Exception('Something bad happened!')

& nbsp; & nbsp; & nbsp; & nbsp;# giá trị trả về không thể truy cập# unreachable return value

& nbsp; & nbsp;return 'Never gets here'

# Bảo vệ điểm vào

if__name__=='__main__':__name__=='__main__':

& nbsp; & nbsp; & nbsp; & nbsp;# tạo một nhóm quy trình# create a process pool

& nbsp; & nbsp; & nbsp; & nbsp; với pool () aspool:with Pool()aspool:

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;## issue a task

        result=pool.apply_async(task)result=pool.apply_async(task)

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# Nhận kết quả# wait for the task to finish

        result.wait()result.wait()

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;## check for a failure

        ifresult.successful():ifresult.successful():

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# get the result

            value=result.get()value =result.get()

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# report the result

            print(value)print(value)

        else:else:

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# report the failure case

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;print('Unable to get the result')

Chạy ví dụ tạo và gửi nhiệm vụ theo bình thường.

Người nhận chờ nhiệm vụ hoàn thành sau đó kiểm tra một trường hợp không thành công.

Sự thất bại của nhiệm vụ được xác định và một thông điệp thích hợp được báo cáo.

Xử lý ngoại lệ khi gọi bản đồ ()

Chúng tôi có thể phát hành nhiều tác vụ cho nhóm quy trình bằng cách sử dụng phiên bản đồng bộ của hàm map () hoặc starmap ().map() function or starmap().

Một hoặc nhiều nhiệm vụ đã phát hành có thể thất bại, điều này sẽ khiến tất cả các nhiệm vụ được ban hành không thành công vì kết quả sẽ không thể truy cập được.

Chúng tôi có thể chứng minh điều này với một ví dụ, được liệt kê dưới đây.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

# SuperfastPython.com

# Ngoại lệ trong một trong nhiều nhiệm vụ được cấp cho nhóm quy trình đồng bộ

từ thời gian nhập vào giấc ngủtime import sleep

từ đa bộ xử lý.pool Poolmultiprocessing.pool import Pool

# Nhiệm vụ được thực hiện trong một quy trình công nhân

nhiệm vụ def (giá trị):task(value):

& nbsp; & nbsp; & nbsp; & nbsp;# block trong giây lát# block for a moment

    sleep(1)sleep(1)

& nbsp; & nbsp; & nbsp; & nbsp;# Kiểm tra trường hợp thất bại# check for failure case

    ifvalue==2:ifvalue== 2:

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;raise Exception('Something bad happened!')

& nbsp; & nbsp; & nbsp; & nbsp;# báo cáo một giá trị# report a value

    returnvaluereturnvalue

# Bảo vệ điểm vào

if__name__=='__main__':__name__ =='__main__':

& nbsp; & nbsp; & nbsp; & nbsp;# tạo một nhóm quy trình# create a process pool

& nbsp; & nbsp; & nbsp; & nbsp; với pool () aspool:with Pool()aspool:

& nbsp; & nbsp; & nbsp; & nbsp;# issues tasks to the process pool

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;for result inpool.map(task,range(5)):

            print(result)print(result)

Chạy ví dụ, tạo nhóm quy trình và phát hành 5 nhiệm vụ bằng Map ().

Một trong 5 nhiệm vụ thất bại với một ngoại lệ.

Ngoại lệ sau đó được tăng lại trong trình gọi thay vì trả về trình lặp qua các giá trị trả về.

multiprocessing.pool.RemoteTraceback:

"" "

Traceback (cuộc gọi gần đây nhất cuối cùng):

...

Ngoại lệ: Một cái gì đó xấu đã xảy ra!

"" "

Traceback (cuộc gọi gần đây nhất cuối cùng):

Traceback (cuộc gọi gần đây nhất cuối cùng):

...

Ngoại lệ: Một cái gì đó xấu đã xảy ra!

Ngoại lệ trên là nguyên nhân trực tiếp của ngoại lệ sau:map(), such as map_async().

Điều này cũng xảy ra khi phát hành các tác vụ bằng các phiên bản không đồng bộ của MAP (), chẳng hạn như MAP_ASYNC ().imap() and imap_unordered(), the exception is not re-raised in the caller until the return value for the specific task that failed is requested from the returned iterator.

Nếu chúng tôi phát hành các tác vụ với IMAP () và IMAP_Unordered (), ngoại lệ sẽ không được nêu lại trong trình gọi cho đến khi giá trị trả về cho tác vụ cụ thể không được yêu cầu từ trình lặp được trả về.

Các ví dụ này nhấn mạnh rằng nếu MAP () hoặc tương đương được sử dụng để phát hành các nhiệm vụ cho nhóm quy trình, thì các tác vụ nên xử lý các trường hợp ngoại lệ của riêng họ hoặc đủ đơn giản để không được mong đợi.

Xử lý ngoại lệ trong các cuộc gọi lại hoàn thành nhiệm vụmultiprocessing.Pool is in callback functions.

Một trường hợp cuối cùng chúng ta phải xem xét để xử lý ngoại lệ khi sử dụng đa xử lý.pool nằm trong các chức năng gọi lại.apply_async() or map_async() we can add a callback function to be called with the result of the task or a callback function to call if there was an error in the task.

Khi phát hành các tác vụ cho nhóm quy trình không đồng bộ với một cuộc gọi đến application_async () hoặc map_async (), chúng tôi có thể thêm chức năng gọi lại để được gọi với kết quả của tác vụ hoặc chức năng gọi lại để gọi nếu có lỗi trong tác vụ.

Ví dụ:

# chức năng gọi lại kết quảresult_callback(result):

    print(result,flush=True)print(result,flush=True)

.....

Ngoại lệ: Một cái gì đó xấu đã xảy ra!

result=apply_async(...,callback=result_callback) =apply_async(...,callback=result_callback)

Ngoại lệ trên là nguyên nhân trực tiếp của ngoại lệ sau:

  • Điều này cũng xảy ra khi phát hành các tác vụ bằng các phiên bản không đồng bộ của MAP (), chẳng hạn như MAP_ASYNC ().

Nếu chúng tôi phát hành các tác vụ với IMAP () và IMAP_Unordered (), ngoại lệ sẽ không được nêu lại trong trình gọi cho đến khi giá trị trả về cho tác vụ cụ thể không được yêu cầu từ trình lặp được trả về.

Các ví dụ này nhấn mạnh rằng nếu MAP () hoặc tương đương được sử dụng để phát hành các nhiệm vụ cho nhóm quy trình, thì các tác vụ nên xử lý các trường hợp ngoại lệ của riêng họ hoặc đủ đơn giản để không được mong đợi.

Xử lý ngoại lệ trong các cuộc gọi lại hoàn thành nhiệm vụ

Một trường hợp cuối cùng chúng ta phải xem xét để xử lý ngoại lệ khi sử dụng đa xử lý.pool nằm trong các chức năng gọi lại.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

# SuperfastPython.com

# Ngoại lệ trong một trong nhiều nhiệm vụ được cấp cho nhóm quy trình đồng bộ

từ thời gian nhập vào giấc ngủtime import sleep

từ đa bộ xử lý.pool Poolmultiprocessing.pool import Pool

# chức năng gọi lại

DEF Handler (kết quả):handler(result):

& nbsp; & nbsp; & nbsp; & nbsp;# kết quả báo cáo# report result

& nbsp; & nbsp; & nbsp; & nbsp; in (kết quả f'got {result} ', flush = true)print(f'Got result {result}',flush=True)

& nbsp; & nbsp; & nbsp; & nbsp;# thất bại với một ngoại lệ# fail with an exception

& nbsp; & nbsp; & nbsp; & nbsp; nâng cao ngoại lệ ('một cái gì đó xấu đã xảy ra!')raise Exception('Something bad happened!')

# Nhiệm vụ được thực hiện trong một quy trình công nhân

nhiệm vụ def ():task():

& nbsp; & nbsp; & nbsp; & nbsp;# block trong giây lát# block for a moment

    sleep(1)sleep(1)

& nbsp; & nbsp; & nbsp; & nbsp;# trả về giá trị# return a value

    return22return22

# Bảo vệ điểm vào

if__name__=='__main__':__name__=='__main__':

& nbsp; & nbsp; & nbsp; & nbsp;# tạo một nhóm quy trình# create a process pool

& nbsp; & nbsp; & nbsp; & nbsp; với pool () aspool:with Pool()aspool:

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# issue a task to the process pool

        result=pool.apply_async(task,callback=handler)result=pool.apply_async(task,callback=handler)

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# wait for the task to finish

        result.wait()result.wait()

Chạy ví dụ bắt đầu nhóm quy trình theo bình thường và phát hành nhiệm vụ.

Khi hoàn thành tác vụ, chức năng gọi lại được gọi là thất bại với một ngoại lệ được nâng cao.

Chủ đề trợ giúp (Chủ đề-3 trong trường hợp này) thư giãn và phanh nhóm quy trình.

Người gọi trong luồng chính của quy trình chính sau đó chờ đợi mãi mãi cho kết quả.

Lưu ý, bạn phải chấm dứt chương trình một cách mạnh mẽ bằng cách nhấn Control-C.

Có kết quả 22

Ngoại lệ trong luồng luồng-3:

Traceback (cuộc gọi gần đây nhất cuối cùng):

...

Ngoại lệ: Một cái gì đó xấu đã xảy ra!

Điều này nhấn mạnh rằng nếu các cuộc gọi lại dự kiến ​​sẽ tăng một ngoại lệ, thì nó phải được xử lý rõ ràng nếu không nó sẽ khiến toàn bộ nhóm quy trình gặp rủi ro.

Đa bộ xử lý nhóm vs ProcessPoolExecort

Trong phần này, chúng tôi sẽ xem xét cách lớp nhóm so sánh với lớp nhóm dựa trên quy trình khác của Python, được gọi là ProcessPoolExecutor.Pool class compares to Python’s other process-based pool class called the ProcessPoolExecutor.

ProcessPoolExecutor là gì

Các lớp đồng thời.concurrent.futures.ProcessPoolExecutor class provides a process pool in Python.

Một quy trình là một ví dụ của một chương trình máy tính. Một quy trình có một luồng thực thi chính và có thể có các luồng bổ sung. Một quá trình cũng có thể sinh sản hoặc nĩa quy trình con. Trong Python, giống như nhiều ngôn ngữ lập trình hiện đại, các quy trình được tạo và quản lý bởi hệ điều hành cơ bản.

Bạn có thể tạo một nhóm quy trình bằng cách khởi tạo lớp và chỉ định số lượng quy trình thông qua đối số MAX_Workers; Ví dụ:max_workers argument; for example:

.....

Ngoại lệ: Một cái gì đó xấu đã xảy ra!

executor=ProcessPoolExecutor(max_workers=10)=ProcessPoolExecutor(max_workers=10)

Điều này nhấn mạnh rằng nếu các cuộc gọi lại dự kiến ​​sẽ tăng một ngoại lệ, thì nó phải được xử lý rõ ràng nếu không nó sẽ khiến toàn bộ nhóm quy trình gặp rủi ro.map() and the submit() functions.

Đa bộ xử lý nhóm vs ProcessPoolExecortmap() function matches the built-in map() function and takes a function name and an iterable of items. The target function will then be called for each item in the iterable as a separate task in the process pool. An iterable of results will be returned if the target function returns a value.

Trong phần này, chúng tôi sẽ xem xét cách lớp nhóm so sánh với lớp nhóm dựa trên quy trình khác của Python, được gọi là ProcessPoolExecutor.map() does not block, but each result yielded in the returned iterator will block until the associated task is completed.

ProcessPoolExecutor là gì

.....

Ngoại lệ: Một cái gì đó xấu đã xảy ra!

Điều này nhấn mạnh rằng nếu các cuộc gọi lại dự kiến ​​sẽ tăng một ngoại lệ, thì nó phải được xử lý rõ ràng nếu không nó sẽ khiến toàn bộ nhóm quy trình gặp rủi ro.result inexecutor.map(task,items):

Đa bộ xử lý nhóm vs ProcessPoolExecort# process result...

Trong phần này, chúng tôi sẽ xem xét cách lớp nhóm so sánh với lớp nhóm dựa trên quy trình khác của Python, được gọi là ProcessPoolExecutor.submit() function that takes the target function name and any arguments and returns a Future object.

ProcessPoolExecutor là gìFuture object can be used to query the status of the task (e.g. done(), running(), or cancelled()) and can be used to get the result or exception raised by the task once completed. The calls to result() and exception() will block until the task associated with the Future is done.

ProcessPoolExecutor là gì

.....

Ngoại lệ: Một cái gì đó xấu đã xảy ra!

future=executor.submit(task,item)=executor.submit(task,item)

Điều này nhấn mạnh rằng nếu các cuộc gọi lại dự kiến ​​sẽ tăng một ngoại lệ, thì nó phải được xử lý rõ ràng nếu không nó sẽ khiến toàn bộ nhóm quy trình gặp rủi ro.

result=future.result()= future.result()

Đa bộ xử lý nhóm vs ProcessPoolExecortshutdown() function in order to release all of the worker processes and their resources.

ProcessPoolExecutor là gì

.....

Ngoại lệ: Một cái gì đó xấu đã xảy ra!

executor.shutdown().shutdown()

Điều này nhấn mạnh rằng nếu các cuộc gọi lại dự kiến ​​sẽ tăng một ngoại lệ, thì nó phải được xử lý rõ ràng nếu không nó sẽ khiến toàn bộ nhóm quy trình gặp rủi ro.shutdown() function.

ProcessPoolExecutor là gì

.....

Ngoại lệ: Một cái gì đó xấu đã xảy ra!

Điều này nhấn mạnh rằng nếu các cuộc gọi lại dự kiến ​​sẽ tăng một ngoại lệ, thì nó phải được xử lý rõ ràng nếu không nó sẽ khiến toàn bộ nhóm quy trình gặp rủi ro.ProcessPoolExecutor(max_workers=10)asexecutor:

Đa bộ xử lý nhóm vs ProcessPoolExecort# call a function on each item in a list and process results

Trong phần này, chúng tôi sẽ xem xét cách lớp nhóm so sánh với lớp nhóm dựa trên quy trình khác của Python, được gọi là ProcessPoolExecutor.for result inexecutor.map(task,items):

ProcessPoolExecutor là gì# process result...

Các lớp đồng thời.# ...

Một quy trình là một ví dụ của một chương trình máy tính. Một quy trình có một luồng thực thi chính và có thể có các luồng bổ sung. Một quá trình cũng có thể sinh sản hoặc nĩa quy trình con. Trong Python, giống như nhiều ngôn ngữ lập trình hiện đại, các quy trình được tạo và quản lý bởi hệ điều hành cơ bản.

Bạn có thể tạo một nhóm quy trình bằng cách khởi tạo lớp và chỉ định số lượng quy trình thông qua đối số MAX_Workers; Ví dụ:ProcessPoolExecutor, see the guide:

  • # Tạo một nhóm quy trình

Sau đó, bạn có thể gửi các tác vụ để được thực hiện bởi nhóm quy trình bằng các hàm bản đồ () và trình gửi ().multiprocessing.Pool and ProcessPoolExecutor, let’s compare and contrast each.

Sự tương đồng giữa Pool và ProcessPoolExecutor

Các lớp đa xử lý.Pool và ProcessPoolExecutor rất giống nhau. Cả hai đều là nhóm quy trình của các quy trình lao động trẻ em.multiprocessing.Pool and ProcessPoolExecutor classes are very similar. They are both process pools of child worker processes.

Những điểm tương đồng quan trọng nhất như sau:

  1. Cả hai quá trình sử dụng
  2. Cả hai đều có thể chạy các tác vụ ad hoc
  3. Cả hai đều hỗ trợ các nhiệm vụ không đồng bộ
  4. Cả hai đều có thể chờ tất cả các nhiệm vụ
  5. Cả hai đều có tương đương dựa trên chủ đề

Hãy cùng nhau xem xét kỹ hơn từng cái.

1. Cả hai quy trình sử dụng

Cả đa xử lý.Pool và ProcessPoolExecutor đều tạo và sử dụng các quy trình nhân viên trẻ em.multiprocessing.Pool and ProcessPoolExecutor create and use child worker processes.

Đây là những quá trình con ở cấp độ tự nhiên hoặc hệ thống thực sự có thể bị rẽ nhánh hoặc sinh sản. Điều này có nghĩa là, chúng được tạo và quản lý bởi hệ điều hành cơ bản.

Do đó, các quy trình con công nhân được sử dụng trong mỗi lớp cung cấp song song thực sự thông qua đồng thời dựa trên quy trình.

Điều này có nghĩa là các nhiệm vụ được cấp cho mỗi nhóm quy trình sẽ thực hiện đồng thời và sử dụng tốt nhất các lõi CPU có sẵn.

Điều đó cũng có nghĩa là, các nhiệm vụ được cấp cho mỗi nhóm quy trình sẽ phải chịu sự giao tiếp giữa các quá trình, yêu cầu dữ liệu được gửi đến các quy trình con và nhận được từ các quy trình con phải được ngâm, thêm chi phí tính toán.

2. Cả hai đều có thể chạy các tác vụ ad hoc

Cả Multiprocessing.Pool và ProcessPoolExecutor đều có thể được sử dụng để thực hiện các tác vụ ad hoc được xác định bởi các chức năng tùy chỉnh.multiprocessing.Pool and ProcessPoolExecutor may be used to execute ad hoc tasks defined by custom functions.

Đa xử lý.pool có thể phát hành các tác vụ một lần bằng hàm application () và application_async () và có thể phát hành nhiều tác vụ sử dụng cùng một hàm với các đối số khác nhau với bản đồ (), imap (), imap_unordered () và starmap () Các chức năng và các tương đương không đồng bộ của chúng map_async () và starmap_async ().multiprocessing.Pool can issue one-off tasks using the apply() and apply_async() function, and may issue multiple tasks that use the same function with different arguments with the map(), imap(), imap_unordered(), and starmap() functions and their asynchronous equivalents map_async() and starmap_async().

ProcessPoolExecutor có thể phát hành các tác vụ một lần thông qua hàm SOUNT () và có thể phát hành nhiều tác vụ sử dụng cùng một hàm với các đối số khác nhau thông qua hàm map ().ProcessPoolExecutor can issue one-off tasks via the submit() function, and may issue multiple tasks that use the same function with different arguments via the map() function.

3. Cả hai đều hỗ trợ các nhiệm vụ không đồng bộ

Cả hai bộ xử lý.Pool và ProcessPoolExecutor đều có thể được sử dụng để ban hành các nhiệm vụ không đồng bộ.multiprocessing.Pool and ProcessPoolExecutor can be used to issue tasks asynchronously.

Hãy nhớ lại rằng việc ban hành các nhiệm vụ không đồng bộ có nghĩa là quá trình chính có thể ban hành một nhiệm vụ mà không bị chặn. Cuộc gọi chức năng sẽ quay lại ngay lập tức với một số xử lý trong nhiệm vụ đã phát hành và cho phép quy trình chính tiếp tục với chương trình.

Đa xử lý.Pool hỗ trợ các tác vụ phát hành không đồng bộ thông qua các hàm application_async (), map_async () và starmap_async () trả về một đối tượng không đồng bộ cung cấp xử lý các tác vụ đã phát hành.multiprocessing.Pool supports issuing tasks asynchronously via the apply_async(), map_async() and starmap_async() functions that return an AsyncResult object that provides a handle on the issued tasks.

ProcessPoolExecutor cung cấp chức năng gửi () để phát hành các tác vụ không đồng bộ mà trả về một đối tượng trong tương lai cung cấp một xử lý cho nhiệm vụ đã phát hành.ProcessPoolExecutor provides the submit() function for issuing tasks asynchronously that returns a Future object that provides a handle on the issued task.

Ngoài ra, cả hai nhóm quy trình cung cấp các cơ chế hữu ích để làm việc với các tác vụ không đồng bộ, chẳng hạn như kiểm tra trạng thái của chúng, nhận kết quả và thêm các chức năng gọi lại.

4. Cả hai có thể chờ tất cả các nhiệm vụ

Cả đa xử lý.Pool và ProcessPoolExecutor đều cung cấp khả năng chờ đợi các nhiệm vụ được ban hành không đồng bộ.multiprocessing.Pool and ProcessPoolExecutor provide the ability to wait for tasks that were issued asynchronously.

Đa xử lý.Pool cung cấp hàm chờ () trên đối tượng Asyncresult được trả về dưới dạng xử lý các tác vụ không đồng bộ. Nó cũng cho phép nhóm được tắt và tham gia, điều này sẽ không trở lại cho đến khi tất cả các nhiệm vụ được phát hành đã hoàn thành.multiprocessing.Pool provides a wait() function on the AsyncResult object returned as a handle on asynchronous tasks. It also allows the pool to be shutdown and joined, which will not return until all issued tasks have completed.

ProcessPoolExecutor cung cấp chức năng mô -đun Wait () có thể lấy một bộ sưu tập các đối tượng trong tương lai để chờ đợi. Nó cũng cho phép nhóm quy trình tắt, có thể được cấu hình để chặn cho đến khi tất cả các tác vụ trong nhóm đã hoàn thành.ProcessPoolExecutor provides the wait() module function that can take a collection of Future objects on which to wait. It also allows the process pool to be shutdown, which can be configured to block until all tasks in the pool have completed.

5. Cả hai đều có tương đương dựa trên chủ đề

Cả hai nhóm quy trình đa xử lý.Pool và ProcessPoolExecutor đều có các tương đương dựa trên luồng.multiprocessing.Pool and ProcessPoolExecutor process pools have thread-based equivalents.

Multiprocessing.pool có đa xử lý.Pool.ThreadPool cung cấp cùng một API, ngoại trừ việc nó sử dụng đồng thời dựa trên luồng thay vì đồng thời dựa trên quy trình.multiprocessing.Pool has the multiprocessing.pool.ThreadPool which provides the same API, except that it uses thread-based concurrency instead of process-based concurrency.

Tương tự, ProcessPoolExecutor có đồng thời.ProcessPoolExecutor has the concurrent.futures.ThreadPoolExecutor that provides the same API as the ProcessPoolExecutor (e.g. extends the same Executor base class) except that it is implemented using thread-based concurrency.

Điều này rất hữu ích vì cả hai nhóm quy trình có thể được sử dụng và chuyển sang sử dụng đồng thời dựa trên luồng với rất ít thay đổi đối với mã chương trình.

Sự khác biệt giữa Pool và ProcessPoolExecutor

Đa xử lý.Pool và ProcessPoolExecutor cũng khác nhau một cách tinh tế.multiprocessing.Pool and ProcessPoolExecutor are also subtly different.

Sự khác biệt giữa hai nhóm quy trình này tập trung vào sự khác biệt trong API trên chính các lớp.

Chúng tôi khác biệt chính như sau:

  1. Khả năng hủy bỏ các nhiệm vụ
  2. Hoạt động trên các nhóm nhiệm vụ
  3. Khả năng chấm dứt tất cả các nhiệm vụ
  4. Chức năng bản đồ không đồng bộ
  5. Khả năng truy cập ngoại lệ

Hãy cùng nhau xem xét kỹ hơn từng cái.

1. Cả hai quy trình sử dụng

Cả đa xử lý.Pool và ProcessPoolExecutor đều tạo và sử dụng các quy trình nhân viên trẻ em.ProcessPoolExecutor can be canceled, whereas tasks issued to the multiprocessing.Pool cannot.

ProcessPoolExecutor cung cấp khả năng hủy các tác vụ đã được cấp cho nhóm quy trình nhưng chưa bắt đầu thực thi.ProcessPoolExecutor provides the ability to cancel tasks that have been issued to the process pool but have not yet started executing.

Điều này được cung cấp thông qua hàm hủy () trên đối tượng trong tương lai được trả về từ việc ban hành một nhiệm vụ thông qua gửi ().cancel() function on the Future object returned from issuing a task via submit().

Đa xử lý.pool không cung cấp khả năng này.multiprocessing.Pool does not provide this capability.

2. Hoạt động trên các nhóm nhiệm vụ

ProcessPoolExecutor cung cấp các công cụ để làm việc với các nhóm tác vụ không đồng bộ, trong khi đó, đa xử lý.pool thì không.ProcessPoolExecutor provides tools to work with groups of asynchronous tasks, whereas the multiprocessing.Pool does not.

Mô -đun đồng thời. Các chức năng này được thiết kế để hoạt động với các bộ sưu tập các đối tượng trong tương lai được trả về khi phát hành các tác vụ không đồng bộ vào nhóm quy trình thông qua hàm gửi ().concurrent.futures module provides the wait() and as_completed() module functions. These functions are designed to work with collections of Future objects returned when issuing tasks asynchronously to the process pool via the submit() function.

Họ cho phép người gọi chờ một sự kiện trên một bộ sưu tập các nhiệm vụ không đồng nhất trong nhóm quy trình, chẳng hạn như tất cả các nhiệm vụ hoàn thành, để nhiệm vụ đầu tiên hoàn thành hoặc cho nhiệm vụ đầu tiên thất bại.

Họ cũng cho phép người gọi xử lý kết quả từ một tập hợp các nhiệm vụ không đồng nhất theo thứ tự các nhiệm vụ được hoàn thành, thay vì lệnh mà các nhiệm vụ được ban hành.

Đa xử lý.pool không cung cấp khả năng này.multiprocessing.Pool does not provide this capability.

2. Hoạt động trên các nhóm nhiệm vụ

ProcessPoolExecutor cung cấp các công cụ để làm việc với các nhóm tác vụ không đồng bộ, trong khi đó, đa xử lý.pool thì không.multiprocessing.Pool provides the ability to forcefully terminate all tasks, whereas the ProcessPoolExecutor does not.

Mô -đun đồng thời. Các chức năng này được thiết kế để hoạt động với các bộ sưu tập các đối tượng trong tương lai được trả về khi phát hành các tác vụ không đồng bộ vào nhóm quy trình thông qua hàm gửi ().multiprocessing.Pool class provides the close() and terminate() functions that will send the SIGTERM and SIGKILL signals to the child worker processes.

Họ cho phép người gọi chờ một sự kiện trên một bộ sưu tập các nhiệm vụ không đồng nhất trong nhóm quy trình, chẳng hạn như tất cả các nhiệm vụ hoàn thành, để nhiệm vụ đầu tiên hoàn thành hoặc cho nhiệm vụ đầu tiên thất bại.

Họ cũng cho phép người gọi xử lý kết quả từ một tập hợp các nhiệm vụ không đồng nhất theo thứ tự các nhiệm vụ được hoàn thành, thay vì lệnh mà các nhiệm vụ được ban hành.ProcessPoolExecutor does not provide this capability.

3. Khả năng chấm dứt tất cả các nhiệm vụ

Đa xử lý.pool cung cấp khả năng chấm dứt mạnh mẽ tất cả các tác vụ, trong khi ProcessPoolExecutor thì không.multiprocessing.Pool provides a focus on map() based concurrency, whereas the ProcessPoolExecutor does not.

Lớp đa xử lý.Pool cung cấp các hàm đóng () và chấm dứt () sẽ gửi tín hiệu Sigterm và Sigkill đến các quy trình nhân viên trẻ em.ProcessPoolExecutor does provide a parallel version of the built-in map() function which will apply the same function to an iterable of arguments. Each function call is issued as a separate task to the process pool.

Những tín hiệu này sẽ khiến các quy trình nhân viên trẻ em dừng lại, ngay cả khi chúng ở giữa việc thực hiện các nhiệm vụ, có thể rời khỏi trạng thái chương trình ở trạng thái không nhất quán.multiprocessing.Pool provides three versions of the built-in map() function for applying the same function to an iterable of arguments in parallel as tasks in the process pool.

Tuy nhiên, ProcessPoolExecutor không cung cấp khả năng này.map(), a lazier version of map() called imap(), and a version of map() that takes multiple arguments for each function call called starmap().

4. Các chức năng bản đồ không đồng bộimap() where the iterable of results has return values in the order that tasks complete rather than the order that tasks are issued called imap_unordered().

Đa xử lý.pool cung cấp một trọng tâm vào đồng thời dựa trên bản đồ (), trong khi ProcessPoolExecutor thì không.map() function called map_async() and of the starmap() function called starmap_async().

Quá trình xử lý đó cung cấp một phiên bản song song của hàm Bản đồ tích hợp () sẽ áp dụng chức năng tương tự cho một đối số có thể lặp lại. Mỗi cuộc gọi chức năng được ban hành như một nhiệm vụ riêng cho nhóm quy trình.multiprocessing.Pool provides 6 parallel versions of the built-in map() function.

Đa xử lý.pool cung cấp ba phiên bản của hàm Bản đồ tích hợp () để áp dụng cùng một hàm cho một đối số có thể lặp lại song song như các tác vụ trong nhóm quy trình.

Chúng là: bản đồ (), một phiên bản lười biếng hơn của map () được gọi là imap () và phiên bản map () có nhiều đối số cho mỗi cuộc gọi hàm gọi là starmap ().ProcessPoolExecutor provides a way to access an exception raised in an asynchronous task directly, whereas the multiprocessing.Pool does not.

Nó cũng cung cấp một phiên bản IMAP () trong đó có thể lặp lại kết quả có các giá trị trả về theo thứ tự các tác vụ hoàn thành thay vì thứ tự các tác vụ được phát hành gọi là imap_unordered ().

Cuối cùng, nó có các phiên bản không đồng bộ của hàm map () có tên MAP_ASYNC () và của hàm starmap () được gọi là starmap_async ().ProcessPoolExecutor provides the ability to directly get an exception raised in a task.

Trong tất cả, đa xử lý.pool cung cấp 6 phiên bản song song của hàm bản đồ tích hợp ().ProcessPoolExecutor asynchronously via the submit() function will return a Future object. The exception() function on the Future object allows the caller to check if an exception was raised in the task, and if so, to access it directly.

5. Khả năng truy cập ngoại lệmultiprocessing.Pool does not provide this ability.

ProcessPoolExecutor cung cấp một cách để truy cập một ngoại lệ được nêu trực tiếp trong một tác vụ không đồng bộ trực tiếp, trong khi đó, đa xử lý.pool thì không.

Cả hai nhóm xử lý đều cung cấp khả năng kiểm tra xem một nhiệm vụ có thành công hay không, và sẽ tìm lại một ngoại lệ khi nhận được kết quả nhiệm vụ, nếu một ngoại lệ được nêu ra và không được xử lý trong nhiệm vụ.multiprocessing.Pool and ProcessPoolExecutor.

multiprocessing.Pool

  • Tuy nhiên, chỉ có ProcessPoolExecutor cung cấp khả năng trực tiếp nhận được một ngoại lệ được nêu ra trong một nhiệm vụ.ProcessPoolExecutor does.
  • Một tác vụ được cấp vào ProcessPoolExecutor không đồng bộ thông qua hàm SOUSM () sẽ trả về một đối tượng trong tương lai. Hàm ngoại lệ () trên đối tượng tương lai cho phép người gọi kiểm tra xem ngoại lệ có được nêu ra trong tác vụ không và nếu vậy, để truy cập trực tiếp.ProcessPoolExecutor does.
  • Đa xử lý.pool không cung cấp khả năng này.ProcessPoolExecutor does not.
  • Tóm tắt sự khác biệtmap() function, whereas the ProcessPoolExecutor does not.
  • Nó có thể giúp tóm tắt sự khác biệt giữa đa xử lý.Pool và ProcessPoolExecutor.ProcessPoolExecutor does.

Không cung cấp khả năng hủy bỏ các tác vụ, trong khi ProcessPoolExecutor.

  • Không cung cấp khả năng làm việc với các bộ sưu tập các nhiệm vụ không đồng nhất, hãy xóa bỏ quá trình sử dụng ProcessPoolExecutor.multiprocessing.Pool does not.
  • Cung cấp khả năng chấm dứt mạnh mẽ tất cả các nhiệm vụ, trong khi ProcessPoolExecutor thì không.multiprocessing.Pool does not.
  • Cung cấp trọng tâm vào các phiên bản song song của hàm map (), trong khi quá trình processPoolExecutor thì không.multiprocessing.Pool does.
  • Không cung cấp nhiều phiên bản song song của hàm map (), trong khi quá trình đa xử lý.pool.multiprocessing.Pool does.
  • Cung cấp khả năng truy cập một ngoại lệ được nêu ra trong một nhiệm vụ, trong khi bộ xử lý đa dụng.pool thì không.multiprocessing.Pool does not.

Hình dưới đây cung cấp một so sánh cạnh nhau hữu ích về sự khác biệt chính giữa đa xử lý.Pool và ProcessPoolExecutor.multiprocessing.Pool and ProcessPoolExecutor.

Hướng dẫn superfast python multiprocessing - đa xử lý python siêu nhanh
Sự khác biệt giữa đa xử lý.Pool và ProcessPoolExecutor

Bộ xử lý đa xử lý thực hành tốt nhất

Bây giờ chúng ta đã biết cách thức đa xử lý.pool hoạt động và cách sử dụng nó, hãy để xem xét một số thực tiễn tốt nhất để xem xét khi đưa các nhóm quy trình vào các chương trình Python của chúng tôi.multiprocessing.Pool works and how to use it, let’s review some best practices to consider when bringing process pools into our Python programs.

Để giữ cho mọi thứ đơn giản, có năm thực hành tốt nhất; họ đang:

  • Thực hành 1: Sử dụng Trình quản lý bối cảnh
  • Thực hành 2: Sử dụng bản đồ () cho các vòng lặp song song
  • Thực hành 3: Sử dụng imap_unordered () cho mã đáp ứng
  • Thực hành 4: Sử dụng map_async () để ban hành các nhiệm vụ không đồng bộ
  • Thực hành 5: Sử dụng các chức năng độc lập làm nhiệm vụ
  • Thực hành 6: Sử dụng cho các nhiệm vụ ràng buộc CPU (có thể)

Hãy để bắt đầu với thực tiễn đầu tiên, đó là sử dụng Trình quản lý bối cảnh.

Thực hành 1: Sử dụng Trình quản lý bối cảnh

Thực hành 2: Sử dụng bản đồ () cho các vòng lặp song song

Thực hành 3: Sử dụng imap_unordered () cho mã đáp ứng

Thực hành 4: Sử dụng map_async () để ban hành các nhiệm vụ không đồng bộ..

Thực hành 5: Sử dụng các chức năng độc lập làm nhiệm vụ

Thực hành 6: Sử dụng cho các nhiệm vụ ràng buộc CPU (có thể)Pool(4)aspool:

Hãy để bắt đầu với thực tiễn đầu tiên, đó là sử dụng Trình quản lý bối cảnh.# ...

Sử dụng trình quản lý bối cảnh khi sử dụng nhóm đa xử lý để đảm bảo nhóm luôn được đóng đúng.

Ví dụ:close() or terminate().

...

Thực hành 4: Sử dụng map_async () để ban hành các nhiệm vụ không đồng bộ..

Thực hành 5: Sử dụng các chức năng độc lập làm nhiệm vụ

executor=Pool(4)=Pool(4)

Thực hành 6: Sử dụng cho các nhiệm vụ ràng buộc CPU (có thể)

executor.close().close()

Hãy để bắt đầu với thực tiễn đầu tiên, đó là sử dụng Trình quản lý bối cảnh.

Sử dụng trình quản lý bối cảnh khi sử dụng nhóm đa xử lý để đảm bảo nhóm luôn được đóng đúng.

  • Ví dụ:

Thực hành 2: Sử dụng bản đồ () cho các vòng lặp song song

Thực hành 3: Sử dụng imap_unordered () cho mã đáp ứngmap() function to dispatch all tasks and process results once all tasks are completed.

Thực hành 4: Sử dụng map_async () để ban hành các nhiệm vụ không đồng bộtask() for each item:

Thực hành 4: Sử dụng map_async () để ban hành các nhiệm vụ không đồng bộ..

Thực hành 5: Sử dụng các chức năng độc lập làm nhiệm vụ

Thực hành 6: Sử dụng cho các nhiệm vụ ràng buộc CPU (có thể)item inmylist:

    result=task(item)result=task(item)

Hãy để bắt đầu với thực tiễn đầu tiên, đó là sử dụng Trình quản lý bối cảnh.# do something...

Sử dụng trình quản lý bối cảnh khi sử dụng nhóm đa xử lý để đảm bảo nhóm luôn được đóng đúng.map() function:

Thực hành 4: Sử dụng map_async () để ban hành các nhiệm vụ không đồng bộ..

Thực hành 5: Sử dụng các chức năng độc lập làm nhiệm vụ

Thực hành 6: Sử dụng cho các nhiệm vụ ràng buộc CPU (có thể)result inmap(task,mylist):

Hãy để bắt đầu với thực tiễn đầu tiên, đó là sử dụng Trình quản lý bối cảnh.# do something...

Sử dụng trình quản lý bối cảnh khi sử dụng nhóm đa xử lý để đảm bảo nhóm luôn được đóng đúng.map() function on the process pool.

Thực hành 4: Sử dụng map_async () để ban hành các nhiệm vụ không đồng bộ..

Thực hành 5: Sử dụng các chức năng độc lập làm nhiệm vụ

Thực hành 6: Sử dụng cho các nhiệm vụ ràng buộc CPU (có thể)result inpool.map(task,mylist):

Hãy để bắt đầu với thực tiễn đầu tiên, đó là sử dụng Trình quản lý bối cảnh.# do something...

Sử dụng trình quản lý bối cảnh khi sử dụng nhóm đa xử lý để đảm bảo nhóm luôn được đóng đúng.map() function if your target task function has side effects.

Ví dụ:map() function if your target task function has no arguments or more than one argument. If you have multiple arguments, you can use the starmap() function instead.

...map() function if you need control over exception handling for each task, or if you would like to get results to tasks in the order that tasks are completed.

# Tạo một nhóm quy trình thông qua Trình quản lý bối cảnhmap() function if you have many tasks (e.g. hundreds or thousands) as all tasks will be dispatched at once. Instead, consider the more lazy imap() function.

với Pool (4) Aspool:map() with the multiprocessing pool in the tutorial:

  • & nbsp; & nbsp; & nbsp; & nbsp;# ...

Thực hành 3: Sử dụng imap_unordered () cho mã đáp ứng

Thực hành 4: Sử dụng map_async () để ban hành các nhiệm vụ không đồng bộimap_unordered() function.

Thực hành 5: Sử dụng các chức năng độc lập làm nhiệm vụPool.map() function, the Pool.imap_unordered() function will iterate the provided iterable one item at a time and issue tasks to the process pool.

Thực hành 6: Sử dụng cho các nhiệm vụ ràng buộc CPU (có thể)Pool.imap() function, the Pool.imap_unordered() function will yield return values in the order that tasks are completed, not the order that tasks were issued to the process pool.

Hãy để bắt đầu với thực tiễn đầu tiên, đó là sử dụng Trình quản lý bối cảnh.

Thực hành 3: Sử dụng imap_unordered () cho mã đáp ứng

Thực hành 4: Sử dụng map_async () để ban hành các nhiệm vụ không đồng bộ..

Thực hành 5: Sử dụng các chức năng độc lập làm nhiệm vụ

Thực hành 6: Sử dụng cho các nhiệm vụ ràng buộc CPU (có thể)result inpool.imap_unordered(task,items):

& nbsp; & nbsp; & nbsp; & nbsp;# ...# ...

Không sử dụng hàm imap_unordered () nếu bạn cần xử lý kết quả theo thứ tự các tác vụ được gửi đến nhóm quy trình, thay vào đó, sử dụng hàm map ().imap_unordered() function if you need to process the results in the order that the tasks were submitted to the process pool, instead, use map() function.

Không sử dụng hàm imap_unordered () Nếu bạn cần kết quả từ tất cả các tác vụ trước khi tiếp tục tham gia chương trình, thay vào đó, bạn có thể tốt hơn khi sử dụng hàm map_async () và hàm asyncresult.wait ().imap_unordered() function if you need results from all tasks before continuing on in the program, instead, you may be better off using map_async() and the AsyncResult.wait() function.

Không sử dụng hàm imap_unordered () cho một vòng lặp song song đơn giản, thay vào đó, bạn có thể tốt hơn khi sử dụng map ().imap_unordered() function for a simple parallel for-loop, instead, you may be better off using map().

Bạn có thể tìm hiểu thêm về hàm imap_unordered () trong hướng dẫn:imap_unordered() function in the tutorial:

  • Nhóm đa xử lý.imap_unordered () trong python

Thực hành 4: Sử dụng map_async () để ban hành các nhiệm vụ không đồng bộ

Nếu bạn cần đưa ra nhiều nhiệm vụ không đồng bộ, ví dụ: FIRE-and-FORGE Sử dụng hàm map_async ().map_async() function.

Hàm map_async () không chặn trong khi hàm được áp dụng cho từng mục trong ITEBLE, thay vào đó, nó trả về một đối tượng không đồng bộ mà từ đó kết quả có thể được truy cập.map_async() function does not block while the function is applied to each item in the iterable, instead it returns a AsyncResult object from which the results may be accessed.

Vì map_async () không chặn, nó cho phép người gọi tiếp tục và truy xuất kết quả khi cần.map_async() does not block, it allows the caller to continue and retrieve the result when needed.

Người gọi có thể chọn gọi hàm Wait () trên đối tượng Asyncresult đã trả về để chờ tất cả các tác vụ đã phát hành hoàn thành hoặc gọi hàm get () .wait() function on the returned AsyncResult object in order to wait for all of the issued tasks to complete, or call the get() function to wait for the task to complete and access an iterable of return values.

Ví dụ:

.....

# Áp dụng chức năng

result=map_async(task,items)=map_async(task,items)

# Đợi tất cả các nhiệm vụ hoàn thành

result.wait().wait()

Không sử dụng hàm map_async () nếu bạn muốn phát hành các tác vụ và sau đó xử lý kết quả sau khi tất cả các tác vụ hoàn tất. Bạn sẽ tốt hơn khi sử dụng hàm map ().map_async() function if you want to issue the tasks and then process the results once all tasks are complete. You would be better off using the map() function.

Không sử dụng hàm map_async () nếu bạn muốn ban hành các tác vụ từng người một cách lười biếng để bảo tồn bộ nhớ, thay vào đó sử dụng hàm imap ().map_async() function if you want to issue tasks one-by-one in a lazy manner in order to conserve memory, instead use the imap() function.

Không sử dụng hàm map_async () nếu bạn muốn ban hành các tác vụ thực hiện nhiều đối số, thay vào đó sử dụng hàm starmap_async ().map_async() function if you wish to issue tasks that take multiple arguments, instead use the starmap_async() function.

Bạn có thể tìm hiểu thêm về hàm map_async () trong hướng dẫn:map_async() function in the tutorial:

  • Nhóm đa xử lý.map_async () trong python

Thực hành 5: Sử dụng các chức năng độc lập làm nhiệm vụ

Sử dụng nhóm đa xử lý nếu các nhiệm vụ của bạn độc lập.

Điều này có nghĩa là mỗi nhiệm vụ không phụ thuộc vào các nhiệm vụ khác có thể thực thi cùng một lúc. Nó cũng có thể có nghĩa là các tác vụ không phụ thuộc vào bất kỳ dữ liệu nào ngoài dữ liệu được cung cấp thông qua các đối số chức năng cho tác vụ.

Nhóm đa xử lý là lý tưởng cho các tác vụ không thay đổi bất kỳ dữ liệu nào, ví dụ: Không có tác dụng phụ, được gọi là các chức năng thuần túy.

Nhóm đa xử lý có thể được tổ chức thành các luồng dữ liệu và đường ống cho sự phụ thuộc tuyến tính giữa các tác vụ, có lẽ với một nhóm đa xử lý cho mỗi loại tác vụ.

Nhóm đa xử lý không được thiết kế cho các nhiệm vụ yêu cầu phối hợp, bạn nên xem xét sử dụng lớp đa xử lý. Lớp xử lý và các mẫu phối hợp như rào cản và semaphore.Barrier and Semaphore.

Các nhóm quy trình không được thiết kế cho các tác vụ yêu cầu đồng bộ hóa, bạn nên xem xét sử dụng lớp đa xử lý. Lớp xử lý và các mẫu khóa như Lock và Rlock thông qua Trình quản lý.multiprocessing.Process class and locking patterns like Lock and RLock via a Manager.

Thực hành 6: Sử dụng cho các nhiệm vụ ràng buộc CPU (có thể)

Nhóm đa xử lý có thể được sử dụng cho các nhiệm vụ ràng buộc IO và các tác vụ gắn CPU.

Tuy nhiên, có lẽ nó phù hợp nhất với các tác vụ gắn CPU, trong khi phần đa xử lý.pool.ThreadPool hoặc ThreadPoolExecutor có lẽ phù hợp nhất cho các nhiệm vụ gắn IO.multiprocessing.pool.ThreadPool or ThreadPoolExecutor are probably best suited for IO-bound tasks.

Các nhiệm vụ ràng buộc CPU là những nhiệm vụ liên quan đến tính toán trực tiếp, ví dụ: Thực hiện hướng dẫn trên dữ liệu trong CPU. Chúng bị ràng buộc bởi tốc độ thực hiện CPU, do đó tên CPU bị ràng buộc.

Điều này không giống như các tác vụ ràng buộc IO phải chờ trên các tài nguyên bên ngoài như đọc hoặc ghi vào hoặc từ các kết nối và tệp mạng.

Ví dụ về các nhiệm vụ liên kết CPU phổ biến có thể phù hợp với đa xử lý.Pool bao gồm:

  • Thao tác truyền thông, ví dụ: Thay đổi kích thước hình ảnh, cắt âm thanh và video, v.v., e.g. resizing images, clipping audio and video, etc.
  • Mã hóa phương tiện hoặc giải mã, ví dụ: Mã hóa âm thanh và video., e.g. encoding audio and video.
  • Tính toán toán học, ví dụ: Fractals, xấp xỉ số, ước tính, v.v., e.g. fractals, numerical approximation, estimation, etc.
  • Đào tạo mô hình, ví dụ: Học máy và trí tuệ nhân tạo., e.g. machine learning and artificial intelligence.
  • Tìm kiếm, ví dụ: Tìm kiếm một từ khóa trong một số lượng lớn các tài liệu., e.g. searching for a keyword in a large number of documents.
  • Xử lý văn bản, ví dụ: Tính toán số liệu thống kê trên một kho tài liệu., e.g. calculating statistics on a corpus of documents.

Đa xử lý.pool có thể được sử dụng cho các tác vụ ràng buộc IO, nhưng nó có thể là một phù hợp hơn so với sử dụng các luồng và đa xử lý.pool.ThreadPool.multiprocessing.Pool can be used for IO bound tasks, but it is probably a less well fit compared to using threads and the multiprocessing.pool.ThreadPool.

Điều này là do hai lý do:

  • Bạn có thể có nhiều chủ đề hơn các quy trình.
  • Các nhiệm vụ ràng buộc IO thường là dữ liệu chuyên sâu.

Số lượng quy trình bạn có thể tạo và quản lý thường khá hạn chế, chẳng hạn như hàng chục hoặc dưới 100.

Trong khi đó, khi bạn đang sử dụng các luồng, bạn có thể có hàng trăm luồng hoặc thậm chí hàng ngàn luồng trong một quy trình. Điều này rất hữu ích cho các hoạt động IO mà nhiều người cần truy cập hoặc quản lý một số lượng lớn các kết nối hoặc tài nguyên đồng thời.

Điều này có thể được đẩy đến hàng chục ngàn kết nối hoặc tài nguyên hoặc thậm chí cao hơn khi sử dụng Asyncio.

Các tác vụ ràng buộc IO thường liên quan đến việc đọc hoặc viết nhiều dữ liệu.

Đây có thể là dữ liệu được đọc hoặc viết từ hoặc đến các kết nối từ xa, cơ sở dữ liệu, máy chủ, tệp, thiết bị bên ngoài, v.v.

Do đó, nếu dữ liệu cần được chia sẻ giữa các quy trình, chẳng hạn như trong một đường ống, có thể yêu cầu dữ liệu được tuần tự hóa (được gọi là ngâm, quá trình tuần tự hóa Python tích hợp) để chuyển từ quy trình này sang quy trình khác. Điều này có thể chậm và rất nhiều bộ nhớ, đặc biệt là đối với một lượng lớn dữ liệu.

Đây không phải là trường hợp khi sử dụng các luồng có thể chia sẻ và truy cập cùng một tài nguyên trong bộ nhớ mà không cần tuần tự hóa dữ liệu.

Các lỗi phổ biến khi sử dụng nhóm đa xử lý

Có một số lỗi phổ biến khi sử dụng đa xử lý.pool.multiprocessing.Pool.

Các lỗi này thường được thực hiện do các lỗi được giới thiệu bởi mã sao chép và thực hiện hoặc từ một sự hiểu lầm nhẹ về cách thức đa xử lý.pool hoạt động.

Chúng tôi sẽ xem xét kỹ hơn một số lỗi phổ biến hơn khi sử dụng đa xử lý.pool, chẳng hạn như:multiprocessing.Pool, such as:

  • Lỗi 1: Quên __main__
  • LRI 2: Sử dụng lệnh gọi hàm trong SUMMT ()
  • Lỗi 3: Sử dụng lệnh gọi hàm trong bản đồ ()
  • Lỗi 4: Chữ ký chức năng không chính xác cho MAP ()
  • Lỗi 5: Chữ ký chức năng không chính xác cho cuộc gọi lại
  • Lỗi 6: Đối số hoặc dữ liệu được chia sẻ không hấp dẫn
  • Lỗi 7: Không Flushing in () câu lệnh

Hãy cùng nhau xem xét kỹ hơn từng cái.

Lỗi 1: Quên __main__

LRI 2: Sử dụng lệnh gọi hàm trong SUMMT ()Pool is forgetting to protect the entry point, e.g. check for the __main__ module.

Lỗi 3: Sử dụng lệnh gọi hàm trong bản đồ ()Process class or the multiprocessing.Pool class we must include a check for the top-level environment. This is specifically the case when using the ‘spawn‘ start method, the default on Win32 and MacOS, but is a good practice anyway.

Lỗi 4: Chữ ký chức năng không chính xác cho MAP ()__name__ is equal to the string ‘__main__‘.

Lỗi 5: Chữ ký chức năng không chính xác cho cuộc gọi lại

Lỗi 6: Đối số hoặc dữ liệu được chia sẻ không hấp dẫn

Lỗi 7: Không Flushing in () câu lệnh

if__name__=='__main__':__name__=='__main__':

Hãy cùng nhau xem xét kỹ hơn từng cái.# ...

Cho đến nay, lỗi lớn nhất khi sử dụng nhóm đa xử lý là quên bảo vệ điểm vào, ví dụ: Kiểm tra mô -đun __main__.__main__ more generally here:

  • Hãy nhớ lại rằng khi sử dụng các quy trình trong Python, chẳng hạn như lớp quy trình hoặc lớp đa xử lý.pool, chúng ta phải bao gồm kiểm tra môi trường cấp cao nhất. Điều này cụ thể là trường hợp khi sử dụng phương thức bắt đầu ‘Spawn, mặc định trên Win32 và MacOS, nhưng dù sao cũng là một thực tiễn tốt.

Chúng ta có thể kiểm tra môi trường cấp cao nhất bằng cách kiểm tra xem có biến tên mô-đun __name__ bằng chuỗi ‘__main__‘ không.

Điều này chỉ ra rằng mã đang chạy ở môi trường mã cấp cao nhất, thay vì được nhập bởi một chương trình hoặc tập lệnh.multiprocessing.Pool without a check for the __main__ module is listed below.

Ví dụ:

# Điểm vào

& nbsp; & nbsp; & nbsp; & nbsp;# ...time import sleep

Bạn có thể tìm hiểu thêm về __main__ nói chung ở đây:multiprocessing import Pool

__main__-Môi trường mã cấp cao nhất

Quên chức năng chính sẽ dẫn đến một lỗi có thể khá khó hiểu.task(value):

Một ví dụ hoàn chỉnh về việc sử dụng đa xử lý.pool mà không cần kiểm tra mô -đun __main__ được liệt kê dưới đây.# block for a moment

    sleep(1)sleep(1)

    returnvaluereturnvalue

# SuperfastPython.com

# Ví dụ về việc không có kiểm tra môi trường cấp cao nhấtPool()aspool:

từ thời gian nhập vào giấc ngủ# submit all tasks

từ nhóm nhập khẩu đa xử lýfor result inpool.map(task,range(5)):

        print(result)print(result)

# Nhiệm vụ tùy chỉnh sẽ ngủ trong một khoảng thời gian thay đổiRuntimeError.

nhiệm vụ def (giá trị):

& nbsp; & nbsp; & nbsp; & nbsp;# block trong giây lát

RuntimeError:

# Bắt đầu nhóm quy trình

với pool () aspool:

& nbsp; & nbsp; & nbsp; & nbsp;# Gửi tất cả các nhiệm vụ

& nbsp; & nbsp; & nbsp; & nbsp; forresult inpool.map (nhiệm vụ, phạm vi (5)):

Chạy ví dụ này sẽ thất bại với RunTimEError.

Traceback (cuộc gọi gần đây nhất cuối cùng):

freeze_support()

& nbsp; & nbsp; & nbsp; & nbsp;# block trong giây lát

# Bắt đầu nhóm quy trình

với pool () aspool:

& nbsp; & nbsp; & nbsp; & nbsp;# Gửi tất cả các nhiệm vụ

  • & nbsp; & nbsp; & nbsp; & nbsp; forresult inpool.map (nhiệm vụ, phạm vi (5)):

Chạy ví dụ này sẽ thất bại với RunTimEError.

Traceback (cuộc gọi gần đây nhất cuối cùng):apply_async() function.

Lỗi 6: Đối số hoặc dữ liệu được chia sẻ không hấp dẫn

& nbsp; & nbsp; & nbsp; & nbsp;# block trong giây lát..

# Bắt đầu nhóm quy trình

result=pool.apply_async(task())=pool.apply_async(task())

với pool () aspool:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

Ví dụ:

# Điểm vào

& nbsp; & nbsp; & nbsp; & nbsp;# ...time import sleep

Bạn có thể tìm hiểu thêm về __main__ nói chung ở đây:multiprocessing import Pool

__main__-Môi trường mã cấp cao nhất

Quên chức năng chính sẽ dẫn đến một lỗi có thể khá khó hiểu.task():

Một ví dụ hoàn chỉnh về việc sử dụng đa xử lý.pool mà không cần kiểm tra mô -đun __main__ được liệt kê dưới đây.# block for a moment

    sleep(1)sleep(1)

# SuperfastPython.comreturn'all done'

# Ví dụ về việc không có kiểm tra môi trường cấp cao nhất

if__name__=='__main__':__name__=='__main__':

từ thời gian nhập vào giấc ngủ# start the process pool

từ nhóm nhập khẩu đa xử lýwith Pool()aspool:

# Nhiệm vụ tùy chỉnh sẽ ngủ trong một khoảng thời gian thay đổi# issue the task

        result=pool.apply_async(task())result=pool.apply_async(task())

nhiệm vụ def (giá trị):# get the result

        value=result.get()value=result.get()

        print(value)print(value)

Chạy ví dụ này sẽ thất bại với một lỗi.

multiprocessing.pool.RemoteTraceback:

"" "

Traceback (cuộc gọi gần đây nhất cuối cùng):

...

TypeError: đối tượng 'str' không thể gọi được

"" "

Traceback (cuộc gọi gần đây nhất cuối cùng):

Traceback (cuộc gọi gần đây nhất cuối cùng):

...

TypeError: đối tượng 'str' không thể gọi được

Ngoại lệ trên là nguyên nhân trực tiếp của ngoại lệ sau:apply_async() to take the name of your function and any arguments, instead of calling the function in the call to execute.

Bạn có thể sửa lỗi bằng cách cập nhật cuộc gọi lên application_async () để lấy tên của chức năng và bất kỳ đối số nào, thay vì gọi hàm trong cuộc gọi để thực thi.

.....

TypeError: đối tượng 'str' không thể gọi được

result=pool.apply_async(task)=pool.apply_async(task)

Ngoại lệ trên là nguyên nhân trực tiếp của ngoại lệ sau:

Bạn có thể sửa lỗi bằng cách cập nhật cuộc gọi lên application_async () để lấy tên của chức năng và bất kỳ đối số nào, thay vì gọi hàm trong cuộc gọi để thực thi.map() function.

Bạn có thể sửa lỗi bằng cách cập nhật cuộc gọi lên application_async () để lấy tên của chức năng và bất kỳ đối số nào, thay vì gọi hàm trong cuộc gọi để thực thi.

.....

TypeError: đối tượng 'str' không thể gọi được

Ngoại lệ trên là nguyên nhân trực tiếp của ngoại lệ sau:result inpool.map(task(),range(5)):

    print(result)print(result)

Bạn có thể sửa lỗi bằng cách cập nhật cuộc gọi lên application_async () để lấy tên của chức năng và bất kỳ đối số nào, thay vì gọi hàm trong cuộc gọi để thực thi.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

Ví dụ:

# Phát hành nhiệm vụ

Lỗi 3: Sử dụng lệnh gọi hàm trong bản đồ ()time import sleep

Một lỗi phổ biến là gọi hàm của bạn khi sử dụng hàm map ().multiprocessing import Pool

# Phát hành tất cả các nhiệm vụ

forresult inpool.map (Task (), phạm vi (5)):task(value):

Một ví dụ hoàn chỉnh với lỗi này được liệt kê dưới đây.# block for a moment

    sleep(1)sleep(1)

# SuperfastPython.comreturn'all done'

# Ví dụ về bản đồ gọi với cuộc gọi chức năng

if__name__=='__main__':__name__=='__main__':

từ thời gian nhập vào giấc ngủ# start the process pool

từ nhóm nhập khẩu đa xử lýwith Pool()aspool:

# chức năng tùy chỉnh được thực hiện trong một quy trình khác# issue all tasks

nhiệm vụ def (giá trị):forresult inpool.map(task(), range(5)):

            print(result)print(result)

& nbsp; & nbsp; & nbsp; & nbsp;# block trong giây látTypeError.

Traceback (cuộc gọi gần đây nhất cuối cùng):

...

& nbsp; & nbsp; & nbsp; & nbsp; return'all đã hoàn thành '

# Bảo vệ điểm vào

& nbsp; & nbsp; & nbsp; & nbsp;# bắt đầu nhóm quy trìnhmap() to pass the name of the target task function instead of a call to the function.

.....

TypeError: đối tượng 'str' không thể gọi được

Ngoại lệ trên là nguyên nhân trực tiếp của ngoại lệ sau:result inpool.map(task,range(5)):

    print(result)print(result)

Bạn có thể sửa lỗi bằng cách cập nhật cuộc gọi lên application_async () để lấy tên của chức năng và bất kỳ đối số nào, thay vì gọi hàm trong cuộc gọi để thực thi.

Ví dụ:map() is to provide no second argument to the function, e.g. the iterable.

Bạn có thể sửa lỗi bằng cách cập nhật cuộc gọi lên application_async () để lấy tên của chức năng và bất kỳ đối số nào, thay vì gọi hàm trong cuộc gọi để thực thi.

.....

TypeError: đối tượng 'str' không thể gọi được

Ngoại lệ trên là nguyên nhân trực tiếp của ngoại lệ sau:result inpool.map(task):

    print(result)print(result)

Bạn có thể sửa lỗi bằng cách cập nhật cuộc gọi lên application_async () để lấy tên của chức năng và bất kỳ đối số nào, thay vì gọi hàm trong cuộc gọi để thực thi.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

Ví dụ:

# Phát hành nhiệm vụ

Lỗi 3: Sử dụng lệnh gọi hàm trong bản đồ ()time import sleep

Một lỗi phổ biến là gọi hàm của bạn khi sử dụng hàm map ().multiprocessing import Pool

# Phát hành tất cả các nhiệm vụ

forresult inpool.map (Task (), phạm vi (5)):task(value):

Một ví dụ hoàn chỉnh với lỗi này được liệt kê dưới đây.# block for a moment

    sleep(1)sleep(1)

# SuperfastPython.comreturn'all done'

# Ví dụ về bản đồ gọi với cuộc gọi chức năng

if__name__=='__main__':__name__=='__main__':

từ thời gian nhập vào giấc ngủ# start the process pool

từ nhóm nhập khẩu đa xử lýwith Pool()aspool:

# chức năng tùy chỉnh được thực hiện trong một quy trình khác# issue all tasks

nhiệm vụ def (giá trị):forresult inpool.map(task):

            print(result)print(result)

& nbsp; & nbsp; & nbsp; & nbsp;# block trong giây látmap() function to iterate over.

& nbsp; & nbsp; & nbsp; & nbsp;# block trong giây látTypeError.

Traceback (cuộc gọi gần đây nhất cuối cùng):

...

& nbsp; & nbsp; & nbsp; & nbsp; return'all đã hoàn thành '

# Bảo vệ điểm vàomap() along with your function name.

.....

TypeError: đối tượng 'str' không thể gọi được

Ngoại lệ trên là nguyên nhân trực tiếp của ngoại lệ sau:result inpool.map(task,range(5)):

    print(result)print(result)

Bạn có thể sửa lỗi bằng cách cập nhật cuộc gọi lên application_async () để lấy tên của chức năng và bất kỳ đối số nào, thay vì gọi hàm trong cuộc gọi để thực thi.

Ví dụ:

Bạn có thể sửa lỗi bằng cách cập nhật cuộc gọi lên application_async () để lấy tên của chức năng và bất kỳ đối số nào, thay vì gọi hàm trong cuộc gọi để thực thi.

Ví dụ:

# Phát hành nhiệm vụhandler():

Lỗi 3: Sử dụng lệnh gọi hàm trong bản đồ ()print(f'Callback got: {result}',flush=True)

Bạn có thể sửa lỗi bằng cách cập nhật cuộc gọi lên application_async () để lấy tên của chức năng và bất kỳ đối số nào, thay vì gọi hàm trong cuộc gọi để thực thi.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

Ví dụ:

# Phát hành nhiệm vụ

Lỗi 3: Sử dụng lệnh gọi hàm trong bản đồ ()time import sleep

Một lỗi phổ biến là gọi hàm của bạn khi sử dụng hàm map ().multiprocessing.pool import Pool

Ví dụ:

# Phát hành nhiệm vụhandler():

Lỗi 3: Sử dụng lệnh gọi hàm trong bản đồ ()print(f'Callback got: {result}',flush=True)

# Phát hành tất cả các nhiệm vụ

forresult inpool.map (Task (), phạm vi (5)):task():

Một ví dụ hoàn chỉnh với lỗi này được liệt kê dưới đây.# block for a moment

    sleep(1)sleep(1)

# SuperfastPython.comreturn 'all done'

# Ví dụ về bản đồ gọi với cuộc gọi chức năng

if__name__=='__main__':__name__=='__main__':

từ thời gian nhập vào giấc ngủ# create and configure the process pool

từ nhóm nhập khẩu đa xử lýwith Pool()aspool:

# chức năng tùy chỉnh được thực hiện trong một quy trình khác# issue tasks to the process pool

        result=pool.apply_async(task,callback=handler)result=pool.apply_async(task,callback=handler)

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# Nhận kết quả# get the result

        value=result.get()value =result.get()

        print(value)print(value)

Chạy ví dụ này sẽ dẫn đến một lỗi khi cuộc gọi lại được gọi bởi nhóm quy trình.

Điều này sẽ phá vỡ nhóm quy trình và chương trình sẽ phải bị giết thủ công bằng một điều khiển-C.

Ngoại lệ trong luồng luồng-3:

Traceback (cuộc gọi gần đây nhất cuối cùng):

...

TypeError: Handler () lấy 0 đối số vị trí nhưng 1 đã được đưa ra

Sửa lỗi này liên quan đến việc cập nhật chữ ký của chức năng gọi lại của bạn để bao gồm kết quả từ tác vụ.

# chức năng gọi lại kết quả

DEF Handler (kết quả):handler(result):

& nbsp; & nbsp; & nbsp; & nbsp;print(f'Callback got: {result}',flush=True)

Bạn có thể tìm hiểu thêm về việc sử dụng các chức năng gọi lại với các tác vụ không đồng bộ trong hướng dẫn:

  • Đa xử lý các chức năng gọi lại hồ bơi trong Python

Lỗi này cũng có thể xảy ra với cuộc gọi lại lỗi và quên thêm lỗi làm đối số trong hàm gọi lại lỗi.

Lỗi 6: Đối số hoặc dữ liệu được chia sẻ không hấp dẫn

Một lỗi phổ biến là chia sẻ dữ liệu giữa các quy trình không thể tuần tự hóa.

Python có một quy trình tuần tự hóa đối tượng tích hợp được gọi là Pickle, trong đó các đối tượng được ngâm hoặc không bị ràng buộc khi tuần tự hóa và không bị hủy.

Khi chia sẻ dữ liệu giữa các quy trình, dữ liệu sẽ tự động ngâm.

Điều này bao gồm các đối số được truyền đến các chức năng tác vụ mục tiêu, dữ liệu được trả về từ các chức năng tác vụ mục tiêu và dữ liệu được truy cập trực tiếp, chẳng hạn như các biến toàn cầu.

Nếu dữ liệu được chia sẻ giữa các quy trình không thể tự động ngâm, thì picklingError sẽ được nâng lên.PicklingError will be raised.

Hầu hết các đối tượng Python bình thường có thể được ngâm.

Ví dụ về các đối tượng không thể dưa chua là những đối tượng có thể có kết nối mở, chẳng hạn như tệp, cơ sở dữ liệu, máy chủ hoặc tương tự.

Chúng ta có thể chứng minh điều này với một ví dụ bên dưới cố gắng vượt qua xử lý tệp như một đối số cho chức năng tác vụ đích.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

# SuperfastPython.com

# Ví dụ về một đối số không dưa chua

từ thời gian nhập vào giấc ngủtime import sleep

từ nhóm nhập khẩu đa xử lýmultiprocessing import Pool

# chức năng tùy chỉnh được thực hiện trong một quy trình khác

nhiệm vụ def (tệp):task(file):

& nbsp; & nbsp; & nbsp; & nbsp;# ghi vào tệp# write to the file

& nbsp; & nbsp; & nbsp; & nbsp; file.write ('Xin chào')file.write('hi there')

& nbsp; & nbsp; & nbsp; & nbsp; return'all đã hoàn thành 'return'all done'

# Bảo vệ điểm vào

if__name__=='__main__':__name__=='__main__':

& nbsp; & nbsp; & nbsp; & nbsp;# Mở tệp# open the file

& nbsp;with open('tmp.txt','w')asfile:

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# Bắt đầu# start the process pool

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;with Pool()aspool:

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# issue the task

            result=pool.apply_async(task,file)result= pool.apply_async(task,file)

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# get the result

            value=result.get()value=result.get()

            print(value)print(value)

Chạy ví dụ, chúng ta có thể thấy rằng nó rơi với một lỗi cho biết rằng đối số không thể được ngâm để truyền cho quy trình của công nhân.

Traceback (cuộc gọi gần đây nhất cuối cùng):

...

TypeError: Handler () lấy 0 đối số vị trí nhưng 1 đã được đưa ra

Sửa lỗi này liên quan đến việc cập nhật chữ ký của chức năng gọi lại của bạn để bao gồm kết quả từ tác vụ.

# chức năng gọi lại kết quả

DEF Handler (kết quả):pickle module.

& nbsp; & nbsp; & nbsp; & nbsp;

Bạn có thể tìm hiểu thêm về việc sử dụng các chức năng gọi lại với các tác vụ không đồng bộ trong hướng dẫn:print() statement from target task functions.

Đa xử lý các chức năng gọi lại hồ bơi trong Pythonprint() statement in Python does not flush output.

Lỗi này cũng có thể xảy ra với cuộc gọi lại lỗi và quên thêm lỗi làm đối số trong hàm gọi lại lỗi.

  • Lỗi 6: Đối số hoặc dữ liệu được chia sẻ không hấp dẫn

Một lỗi phổ biến là chia sẻ dữ liệu giữa các quy trình không thể tuần tự hóa.

Python có một quy trình tuần tự hóa đối tượng tích hợp được gọi là Pickle, trong đó các đối tượng được ngâm hoặc không bị ràng buộc khi tuần tự hóa và không bị hủy.print() function from spawned or forked processes because standard out will buffer output by default.

Điều này có nghĩa là nếu bạn gọi print () từ các hàm tác vụ mục tiêu trong đa xử lý.pool, bạn có thể sẽ không thấy các câu lệnh in trên tiêu chuẩn cho đến khi các quy trình của công nhân bị đóng.print() from target task functions in the multiprocessing.pool, you probably will not see the print statements on standard out until the worker processes are closed.

Điều này sẽ gây nhầm lẫn vì nó sẽ trông giống như chương trình của bạn không hoạt động chính xác, ví dụ: có lỗi.

Ví dụ dưới đây thể hiện điều này với hàm tác vụ mục tiêu sẽ gọi Print () để báo cáo một số trạng thái.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

# SuperfastPython.com

# Ví dụ về không xả đầu ra khi cuộc gọi in () từ các tác vụ trong các quy trình mới

từ thời gian nhập vào giấc ngủtime import sleep

từ nhập ngẫu nhiên ngẫu nhiênrandom import random

từ nhóm nhập khẩu đa xử lýmultiprocessing import Pool

# chức năng tùy chỉnh được thực hiện trong một quy trình khác

nhiệm vụ def (giá trị):task(value):

& nbsp; & nbsp; & nbsp; & nbsp;# block trong giây lát# block for a moment

    sleep(random())sleep(random())

& nbsp; & nbsp; & nbsp; & nbsp;# báo cáo một tin nhắn# report a message

& nbsp; & nbsp; & nbsp; & nbsp; print (f'done: {value} '))print(f'Done: {value}')

# Bảo vệ điểm vào

if__name__=='__main__':__name__=='__main__':

& nbsp; & nbsp; & nbsp; & nbsp;# bắt đầu nhóm quy trình# start the process pool

& nbsp; & nbsp; & nbsp; & nbsp; với pool () aspool:with Pool()aspool:

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;## submit all tasks

        pool.map(task,range(5))pool.map(task,range(5))

Chạy ví dụ sẽ đợi cho đến khi tất cả các tác vụ trong nhóm quy trình đã hoàn thành trước khi in tất cả các tin nhắn trên tiêu chuẩn.

Xong: 0

Xong: 1

Xong: 2

Xong: 3

Xong: 4

Tất cả đã được làm xong!

Điều này có thể được sửa bằng cách cập nhật tất cả các cuộc gọi lên câu lệnh in () được gọi từ các chức năng tác vụ mục tiêu để xóa đầu ra sau mỗi cuộc gọi.print() statement called from target task functions to flush output after each call.

Điều này có thể đạt được bằng cách đặt đối số của Flush Flush thành True, ví dụ:flush” argument to True, for example:

.....

# Báo cáo một tin nhắn

print (f'done: {value} ', flush = true)(f'Done: {value}',flush=True)

Bạn có thể tìm hiểu thêm về in từ các quá trình trẻ em trong hướng dẫn:

  • Cách in () từ một quá trình trẻ em ở Python

Những câu hỏi phổ biến khi sử dụng nhóm đa xử lý

Phần này trả lời các câu hỏi phổ biến của các nhà phát triển khi sử dụng đa xử lý.pool.multiprocessing.Pool.

Bạn có câu hỏi về đa xử lý.pool? Đặt câu hỏi của bạn trong các bình luận bên dưới và tôi sẽ cố gắng hết sức để trả lời nó và có lẽ thêm nó vào danh sách các câu hỏi này.
Ask your question in the comments below and I will do my best to answer it and perhaps add it to this list of questions.

Làm thế nào để bạn ngừng chạy các nhiệm vụ một cách an toàn?

Nhóm quy trình không cung cấp một cơ chế để ngăn chặn một cách an toàn tất cả các nhiệm vụ hiện đang chạy.

Nó cung cấp một cách để chấm dứt mạnh mẽ tất cả các quy trình công nhân đang chạy thông qua hàm chấm dứt (). Cách tiếp cận này quá tích cực đối với hầu hết các trường hợp sử dụng vì điều đó có nghĩa là nhóm quy trình không còn có thể được sử dụng.terminate() function. This approach is too aggressive for most use cases as it will mean the process pool can no longer be used.

Thay vào đó, chúng ta có thể phát triển một cơ chế để ngăn chặn tất cả các tác vụ chạy một cách an toàn trong một nhóm quy trình bằng cách sử dụng đối tượng đa xử lý.multiprocessing.Event object.

Đầu tiên, một đối tượng sự kiện phải được tạo và chia sẻ giữa tất cả các tác vụ đang chạy.Event object must be created and shared among all running tasks.

Ví dụ:

.....

# Báo cáo một tin nhắn

event=multiprocessing.Event()=multiprocessing.Event()

print (f'done: {value} ', flush = true)

Bạn có thể tìm hiểu thêm về in từ các quá trình trẻ em trong hướng dẫn:is_set() function and made True via the set() function.

Cách in () từ một quá trình trẻ em ở Pythonmultiprocessing.Event in the tutorial:

  • Những câu hỏi phổ biến khi sử dụng nhóm đa xử lý

Phần này trả lời các câu hỏi phổ biến của các nhà phát triển khi sử dụng đa xử lý.pool.multiprocessing.Event object cannot be passed as an argument to task functions executed in the process pool.

Bạn có câu hỏi về đa xử lý.pool? Đặt câu hỏi của bạn trong các bình luận bên dưới và tôi sẽ cố gắng hết sức để trả lời nó và có lẽ thêm nó vào danh sách các câu hỏi này.Event with tasks in the pool.

  • Làm thế nào để bạn ngừng chạy các nhiệm vụ một cách an toàn?Event as a global variable and inherit the global variable in the child process. This will only work for child processes created using the ‘fork’ start method.
  • Nhóm quy trình không cung cấp một cơ chế để ngăn chặn một cách an toàn tất cả các nhiệm vụ hiện đang chạy.Event using a Manager, then inherit the global variable or pass it as an argument. This works with both ‘spawn’ and ‘fork’ start methods.

Nó cung cấp một cách để chấm dứt mạnh mẽ tất cả các quy trình công nhân đang chạy thông qua hàm chấm dứt (). Cách tiếp cận này quá tích cực đối với hầu hết các trường hợp sử dụng vì điều đó có nghĩa là nhóm quy trình không còn có thể được sử dụng.

Thay vào đó, chúng ta có thể phát triển một cơ chế để ngăn chặn tất cả các tác vụ chạy một cách an toàn trong một nhóm quy trình bằng cách sử dụng đối tượng đa xử lý.multiprocessing.Manager creates a process and is responsible for managing a centralized version of an object. It then provides proxy objects that can be used in other processes that keep up-to-date with the single centralized object.

Đầu tiên, một đối tượng sự kiện phải được tạo và chia sẻ giữa tất cả các tác vụ đang chạy.Manager is a useful way to centralize a synchronization primitive like an event shared among multiple worker processes.

Ví dụ:multiprocessing.Manager using the context manager interface.

Ví dụ:

.....

# Báo cáo một tin nhắn

print (f'done: {value} ', flush = true)Manager()asmanager:

Bạn có thể tìm hiểu thêm về in từ các quá trình trẻ em trong hướng dẫn:# ...

Cách in () từ một quá trình trẻ em ở PythonEvent object using the manager.

Những câu hỏi phổ biến khi sử dụng nhóm đa xử lýEvent object in the manager process that we can share among child worker processes directly or indirectly.

Ví dụ:

.....

# Báo cáo một tin nhắn

event=manager.Event()=manager.Event()

print (f'done: {value} ', flush = true)

Bạn có thể tìm hiểu thêm về in từ các quá trình trẻ em trong hướng dẫn:Event as an argument to the target task function.

Ví dụ:

# Tạo một sự kiện được chia sẻ

DEF TASK (Sự kiện, ...):task(event,...):

& nbsp; & nbsp; & nbsp; & nbsp;# ...# ...

Hàm tùy chỉnh thực thi nhiệm vụ có thể kiểm tra trạng thái của đối tượng sự kiện theo định kỳ, chẳng hạn như mỗi lần lặp của một vòng lặp.Event object periodically, such as each iteration of a loop.

Nếu đặt sự kiện, chức năng tác vụ đích sau đó có thể chọn dừng, đóng bất kỳ tài nguyên nào nếu cần thiết.Event set, the target task function can then choose to stop, closing any resources if necessary.

# chức năng được thực thi trong các quy trình công nhân

DEF TASK (Sự kiện, ...):task(event,...):

& nbsp; & nbsp; & nbsp; & nbsp;# ...# ...

    whileTrue:whileTrue:

Hàm tùy chỉnh thực thi nhiệm vụ có thể kiểm tra trạng thái của đối tượng sự kiện theo định kỳ, chẳng hạn như mỗi lần lặp của một vòng lặp.# ...

        ifevent.is_set():if event.is_set():

            returnreturn

Nếu đặt sự kiện, chức năng tác vụ đích sau đó có thể chọn dừng, đóng bất kỳ tài nguyên nào nếu cần thiết.

# chức năng được thực thi trong các quy trình công nhân

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# ...

Ví dụ dưới đây cung cấp một mẫu bạn có thể sử dụng để thêm cờ sự kiện vào chức năng tác vụ mục tiêu của mình để kiểm tra điều kiện dừng để tắt tất cả các tác vụ đang chạy hiện đang chạy.

Một ví dụ hoàn chỉnh để chứng minh điều này được liệt kê dưới đây.time import sleep

# SuperfastPython.commultiprocessing import Event

# Ví dụ về việc dừng an toàn tất cả các nhiệm vụ trong nhóm quy trìnhmultiprocessing import Manager

từ thời gian nhập vào giấc ngủmultiprocessing.pool import Pool

Từ sự kiện nhập khẩu đa xử lý

từ Trình quản lý nhập khẩu đa xử lýtask(identifier,event):

từ đa bộ xử lý.pool Poolprint(f'Task {identifier} running',flush=True)

# Nhiệm vụ được thực hiện trong một quy trình công nhân# run for a long time

    foriinrange(10):foriinrange(10):

DEF TASK (Định danh, Sự kiện):# block for a moment

        sleep(1)sleep(1)

& nbsp; & nbsp; & nbsp; & nbsp;# check if the task should stop

        ifevent.is_set():ifevent.is_set():

& nbsp; & nbsp; & nbsp; & nbsp;# chạy trong một thời gian dàiprint(f'Task {identifier} stopping...',flush=True)

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# stop the task

            breakbreak

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# report all done

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;print(f'Task {identifier} Done', flush=True)

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

if__name__=='__main__':__name__=='__main__':

& nbsp; & nbsp; & nbsp; & nbsp;# báo cáo tất cả đã hoàn thành# create the manager

& nbsp; & nbsp; & nbsp; & nbsp;with Manager()as manager:

# Bảo vệ điểm vào# create the shared event

        event=manager.Event()event=manager.Event()

& nbsp; & nbsp; & nbsp; & nbsp;# tạo trình quản lý# create and configure the process pool

& nbsp; & nbsp; & nbsp; & nbsp; với trình quản lý () asmanager:with Pool()aspool:

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# prepare arguments

            items=[(i,event)foriinrange(4)]items=[(i,event) foriinrange(4)]

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# issue tasks asynchronously

            result=pool.starmap_async(task,items)result= pool.starmap_async(task,items)

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# wait a moment

            sleep(2)sleep(2)

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# safely stop the issued tasks

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;print('Safely stopping all tasks')

            event.set()event.set()

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# wait for all tasks to stop

            result.wait()result.wait()

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;print('All stopped')

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

Chạy ví dụ đầu tiên tạo ra người quản lý, sau đó tạo đối tượng sự kiện được chia sẻ từ người quản lý.

Nhóm quy trình sau đó được tạo bằng cấu hình mặc định.

Các đối số cho các nhiệm vụ được chuẩn bị, sau đó bốn nhiệm vụ được ban hành không đồng bộ vào nhóm quy trình.AsyncResult for the issued tasks to stop.

Quá trình chính sau đó chặn trong giây lát.

Mỗi nhiệm vụ bắt đầu, báo cáo một tin nhắn sau đó bắt đầu vòng lặp chính của nó.

Quá trình chính thức dậy và thiết lập sự kiện, yêu cầu tất cả các nhiệm vụ được ban hành dừng lại. Sau đó, nó chờ đợi sự không đồng bộ để các nhiệm vụ được ban hành dừng lại.

Mỗi tác vụ kiểm tra trạng thái của sự kiện mỗi lần lặp của vòng lặp chính của nó. Họ nhận thấy rằng sự kiện được đặt, phá vỡ vòng lặp chính của họ, báo cáo một tin nhắn cuối cùng sau đó quay lại, dừng nhiệm vụ một cách an toàn.

Tất cả các nhiệm vụ dừng lại, cho phép quy trình chính tiếp tục, kết thúc ứng dụng.

Điều này làm nổi bật cách chúng ta có thể ngăn chặn tất cả các nhiệm vụ một cách an toàn trong nhóm quy trình một cách được kiểm soát.

Nhiệm vụ 0 đang chạy

Dừng lại mọi nhiệm vụ một cách an toàn

Nhiệm vụ 1 dừng lại ...

Nhiệm vụ 1 đã hoàn thành

Nhiệm vụ 0 dừng ...

Nhiệm vụ 0 xong

Nhiệm vụ 3 dừng ...

Nhiệm vụ 3 thực hiện

Nhiệm vụ 2 dừng lại ...

Nhiệm vụ 2 thực hiện

Tất cả dừng lại

Bạn có thể tìm hiểu thêm về cách dừng tất cả các nhiệm vụ một cách an toàn trong nhóm đa xử lý trong hướng dẫn:

  • Dừng mọi nhiệm vụ trong nhóm đa xử lý ở Python

Làm thế nào để giết tất cả các nhiệm vụ?

Giết sát nhiệm vụ trong nhóm quá trình là một cách tiếp cận tích cực.

Nó có thể gây ra các tác dụng phụ không mong muốn.

Ví dụ, việc tiêu diệt các tác vụ trong quá trình trong khi chúng đang chạy có thể có nghĩa là các tài nguyên như tệp, ổ cắm và cấu trúc dữ liệu được sử dụng bởi các tác vụ chạy không được đóng hoặc để ở trạng thái hữu ích.

Một giải pháp thay thế để giết chết các nhiệm vụ mạnh mẽ có thể là tạm dừng một cách an toàn hoặc dừng một nhiệm vụ bằng cách sử dụng một nguyên thủy đồng bộ hóa như một đối tượng đa xử lý.multiprocessing.Event object.

Đa xử lý.pool.pool không cung cấp một cơ chế để tiêu diệt tất cả các nhiệm vụ và tiếp tục sử dụng nhóm.multiprocessing.pool.Pool does not provide a mechanism to kill all tasks and continue using the pool.

Tuy nhiên, nhóm quy trình cung cấp hàm chấm dứt () sẽ chấm dứt tất cả các quy trình nhân viên trẻ em ngay lập tức, lần lượt giết chết tất cả các nhiệm vụ.terminate() function which will forcefully terminate all child worker processes immediately, in turn killing all tasks.

Ví dụ:

.....

# chấm dứt mạnh mẽ nhóm quy trình và tiêu diệt tất cả các nhiệm vụ

pool.terminate().terminate()

Điều này đạt được bằng cách gửi tín hiệu Sigkill cho mỗi quy trình nhân viên trẻ em trong nhóm quy trình. Tín hiệu này không thể được xử lý và ngay lập tức chấm dứt các quá trình con.SIGKILL signal to each child worker process in the process pool. This signal cannot be handled and immediately terminates the child processes.

Bạn có thể tìm hiểu thêm về việc tắt nhóm quy trình trong hướng dẫn:

  • Cách tắt nhóm Quy trình trong Python

Nhóm quy trình có thể mất một chút thời gian để giết mạnh tất cả các quá trình trẻ em, do đó, đó là một thông lệ tốt để gọi hàm tham gia () sau khi gọi chấm dứt (). Hàm tham gia () sẽ chỉ quay lại sau khi tất cả các quy trình nhân viên trẻ em được đóng hoàn toàn.join() function after calling terminate(). The join() function will only return after all child worker processes are completely closed.

Ví dụ:

.....

# chấm dứt mạnh mẽ nhóm quy trình và tiêu diệt tất cả các nhiệm vụ

pool.terminate().terminate()

Điều này đạt được bằng cách gửi tín hiệu Sigkill cho mỗi quy trình nhân viên trẻ em trong nhóm quy trình. Tín hiệu này không thể được xử lý và ngay lập tức chấm dứt các quá trình con.

pool.join().join()

Bạn có thể tìm hiểu thêm về việc tắt nhóm quy trình trong hướng dẫn:

Cách tắt nhóm Quy trình trong Pythonapply_async(), map_async() and starmap_async() to issue tasks.

Nhóm quy trình có thể mất một chút thời gian để giết mạnh tất cả các quá trình trẻ em, do đó, đó là một thông lệ tốt để gọi hàm tham gia () sau khi gọi chấm dứt (). Hàm tham gia () sẽ chỉ quay lại sau khi tất cả các quy trình nhân viên trẻ em được đóng hoàn toàn.terminate() function.

# Đợi một chút thời gian để tất cả các quy trình công nhân dừng lại

Việc giết các nhiệm vụ trong nhóm quy trình giả định rằng quy trình chính phát hành các nhiệm vụ cho nhóm quy trình là miễn phí và có thể tiêu diệt nhóm quy trình.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

Điều này có nghĩa là các nhiệm vụ được cấp cho nhóm quy trình được ban hành một cách không đồng bộ thay vì đồng bộ. Điều này có thể đạt được bằng cách sử dụng các hàm như application_async (), map_async () và starmap_async () để phát hành các tác vụ.

Chúng ta có thể khám phá cách giết mạnh các tác vụ đang chạy trong nhóm quy trình với hàm chấm dứt ().

Trong ví dụ này, chúng tôi sẽ đưa ra một số lượng nhỏ các nhiệm vụ chạy trong một thời gian dài. Sau đó, chúng tôi sẽ đợi một lúc sau đó chấm dứt mạnh mẽ nhóm quy trình và tất cả các nhiệm vụ đang chạy trong nhóm.time import sleep

Một ví dụ hoàn chỉnh để chứng minh điều này được liệt kê dưới đây.multiprocessing.pool import Pool

# SuperfastPython.com

# Ví dụ về việc giết tất cả các nhiệm vụ trong nhóm quy trìnhtask(identifier):

từ thời gian nhập vào giấc ngủprint(f'Task {identifier} running',flush=True)

từ đa bộ xử lý.pool Pool# run for a long time

    foriinrange(10):foriinrange(10):

# Nhiệm vụ được thực hiện trong một quy trình công nhân# block for a moment

        sleep(1)sleep(1)

Nhiệm vụ Def (Định danh):# report all done

& nbsp; & nbsp; & nbsp; & nbsp;print(f'Task {identifier} Done',flush=True)

& nbsp; & nbsp; & nbsp; & nbsp;# chạy trong một thời gian dài

if__name__=='__main__': __name__=='__main__':

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# create and configure the process pool

& nbsp; & nbsp; & nbsp; & nbsp;# báo cáo tất cả đã hoàn thànhwith Pool()aspool:

& nbsp; & nbsp; & nbsp; & nbsp;# issues tasks to process pool

        _=pool.map_async(task,range(4))_ =pool.map_async(task,range(4))

# Bảo vệ điểm vào# wait a moment

        sleep(2)sleep(2)

& nbsp; & nbsp; & nbsp; & nbsp;# tạo và định cấu hình nhóm quy trình# kill all tasks

& nbsp; & nbsp; & nbsp; & nbsp; với pool () aspool:print('Killing all tasks')

        pool.terminate()pool.terminate()

& nbsp; & nbsp;# wait for the pool to close down

        pool.join()pool.join()

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

Chạy ví dụ đầu tiên tạo nhóm quy trình với cấu hình mặc định.SIGKILL signal to each child worker process causing them to terminate immediately. In turn the tasks that each child worker process is executing is forcefully terminated immediately.

Quá trình chính sau đó chặn một phần nhỏ một giây cho đến khi các quy trình nhân viên trẻ em được dừng lại, sau đó tiếp tục, đóng ứng dụng.

Nhiệm vụ 0 đang chạy

Nhiệm vụ 1 đang chạy

Nhiệm vụ 2 đang chạy

Nhiệm vụ 3 đang chạy

Giết tất cả các nhiệm vụ

Bạn có thể tìm hiểu thêm về việc giết tất cả các nhiệm vụ trong nhóm quy trình trong hướng dẫn:

  • Giết tất cả các nhiệm vụ trong nhóm đa xử lý trong Python

Làm thế nào để bạn chờ đợi tất cả các nhiệm vụ hoàn thành?

Dưới đây là hai cách mà chúng ta có thể chờ đợi các nhiệm vụ hoàn thành trong đa xử lý.pool.pool.multiprocessing.pool.Pool.

Họ đang:

  • Đợi một tập hợp các tác vụ không đồng bộ hoàn thành với hàm chờ ().wait() function.
  • Đợi tất cả các tác vụ được cấp hoàn thành sau khi tắt máy với hàm tham gia ().join() function.

Hãy cùng xem xét kỹ hơn về từng cách tiếp cận.

Nhiệm vụ có thể được ban hành không đồng bộ vào nhóm quy trình.

Điều này có thể đạt được bằng cách sử dụng một hàm như application_async (), map_async () và starmap_async (). Các chức năng này trả về một đối tượng không đồng bộ.apply_async(), map_async(), and starmap_async(). These functions return an AsyncResult object.

Chúng ta có thể chờ một loạt các tác vụ được phát hành không đồng bộ vào nhóm quy trình để hoàn thành bằng cách gọi hàm Wait () trên đối tượng Asyncresult được trả về.wait() function on the returned AsyncResult object.

Ví dụ:

.....

# Phát hành nhiệm vụ

result=pool.map_async(...)=pool.map_async(...)

# Chờ các nhiệm vụ đã cấp để hoàn thành

result.wait().wait()

Nếu nhiều loạt các tác vụ không đồng bộ được cấp cho nhóm quy trình, chúng ta có thể thu thập các đối tượng không đồng bộ được trả lại và chờ lần lượt chờ đợi.AsyncResult objects that are returned and wait on each in turn.

Chúng tôi có thể phát hành nhiều lô các nhiệm vụ không đồng bộ vào nhóm quy trình và không bị treo vào các đối tượng không đồng bộ được trả về.AsyncResult objects that are returned.

Thay vào đó, chúng tôi có thể chờ tất cả các nhiệm vụ trong nhóm quy trình hoàn thành bằng cách lần đầu tiên tắt nhóm quy trình, sau đó tham gia để chờ tất cả các nhiệm vụ được phát hành được hoàn thành.

Điều này có thể đạt được bằng cách gọi đầu tiên chức năng đóng () sẽ ngăn chặn bất kỳ nhiệm vụ nào được cấp thêm cho nhóm quy trình và đóng các quy trình của công nhân sau khi tất cả các nhiệm vụ hoàn tất.close() function that will prevent any further tasks to be issued to the process pool and close down the worker processes once all tasks are complete.

Sau đó chúng ta có thể gọi hàm Jopnow (). Điều này sẽ chặn người gọi cho đến khi tất cả các tác vụ trong nhóm quy trình được hoàn thành và các quy trình con của người lao động trong nhóm quy trình đã đóng.join() function. This will block the caller until all tasks in the process pools are completed and the worker child processes in the process pool have closed.

Ví dụ:

.....

# Phát hành nhiệm vụ

pool.close().close()

# Chờ các nhiệm vụ đã cấp để hoàn thành

pool.join().join()

Nếu nhiều loạt các tác vụ không đồng bộ được cấp cho nhóm quy trình, chúng ta có thể thu thập các đối tượng không đồng bộ được trả lại và chờ lần lượt chờ đợi.

Chúng tôi có thể phát hành nhiều lô các nhiệm vụ không đồng bộ vào nhóm quy trình và không bị treo vào các đối tượng không đồng bộ được trả về.

Thay vào đó, chúng tôi có thể chờ tất cả các nhiệm vụ trong nhóm quy trình hoàn thành bằng cách lần đầu tiên tắt nhóm quy trình, sau đó tham gia để chờ tất cả các nhiệm vụ được phát hành được hoàn thành.AsyncResult object.

Điều này có thể đạt được bằng cách gọi đầu tiên chức năng đóng () sẽ ngăn chặn bất kỳ nhiệm vụ nào được cấp thêm cho nhóm quy trình và đóng các quy trình của công nhân sau khi tất cả các nhiệm vụ hoàn tất.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

Sau đó chúng ta có thể gọi hàm Jopnow (). Điều này sẽ chặn người gọi cho đến khi tất cả các tác vụ trong nhóm quy trình được hoàn thành và các quy trình con của người lao động trong nhóm quy trình đã đóng.

# Đóng nhóm quy trình

# chặn cho đến khi tất cả các tác vụ hoàn tất và các quy trình đóngtime import sleep

Nhược điểm của phương pháp này là chúng tôi không thể phát hành các nhiệm vụ cho nhóm sau khi nó được đóng lại. Cách tiếp cận này chỉ có thể được sử dụng một khi bạn biết rằng bạn không có nhiệm vụ nào nữa để phát hành cho nhóm quy trình.multiprocessing.pool import Pool

Chúng ta có thể khám phá cách chờ đợi một loạt các nhiệm vụ đã cấp để hoàn thành trong nhóm quy trình.

Trong ví dụ này, chúng tôi sẽ xác định một nhiệm vụ chặn trong một khoảnh khắc và sau đó báo cáo một tin nhắn. Từ quy trình chính, chúng tôi sẽ phát hành một loạt các nhiệm vụ cho nhóm quá trình không đồng bộ. Sau đó, chúng tôi sẽ chờ đợi rõ ràng trên lô các tác vụ để hoàn thành bằng cách chờ đợi đối tượng Asynresult được trả về.task(identifier):

Một ví dụ hoàn chỉnh để chứng minh điều này được liệt kê dưới đây.# block for a moment

    sleep(0.5)sleep(0.5)

# SuperfastPython.com# report done

# Ví dụ về việc chờ đợi tất cả các nhiệm vụ trong một đợt để hoàn thànhprint(f'Task {identifier} done',flush=True)

từ thời gian nhập vào giấc ngủ

if__name__=='__main__': __name__=='__main__':

từ đa bộ xử lý.pool Pool# create and configure the process pool

# Nhiệm vụ được thực hiện trong một quy trình công nhânwith Pool()aspool:

Nhiệm vụ Def (Định danh):# issue tasks into the process pool

        result=pool.map_async(task,range(10))result=pool.map_async(task,range(10))

& nbsp; & nbsp; & nbsp; & nbsp;# block trong giây lát# wait for tasks to complete

        result.wait()result.wait()

& nbsp; & nbsp; & nbsp; & nbsp;# báo cáo đã hoàn thành# report all tasks done

& nbsp; & nbsp; & nbsp; & nbsp;print('All tasks are done',flush=True)

# Bảo vệ điểm vào# process pool is closed automatically

& nbsp; & nbsp; & nbsp; & nbsp;# tạo và định cấu hình nhóm quy trình

& nbsp; & nbsp; & nbsp; & nbsp; với pool () aspool:AsyncResult object is returned and the main process then blocks until the issued tasks are completed.

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# vấn đề

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;wait() function returns and the main process continues on.

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# Báo cáo tất cả

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

& nbsp; & nbsp; & nbsp; & nbsp;# pool được đóng tự động

Chạy ví dụ đầu tiên tạo ra nhóm quy trình.

Mười nhiệm vụ sau đó được cấp cho nhóm quy trình không đồng bộ. Một đối tượng không đồng bộ được trả về và quy trình chính sau đó chặn cho đến khi các tác vụ được phát hành được hoàn thành.

Mỗi nhiệm vụ được ban hành trong nhóm quy trình, đầu tiên chặn cho một phần nhỏ của một giây, sau đó in một tin nhắn.

Tất cả mười nhiệm vụ được phát hành dưới dạng một lô cho nhóm quy trình hoàn tất, sau đó chờ () hàm trả về và quy trình chính vẫn tiếp tục.

Một thông báo cuối cùng được báo cáo, sau đó nhóm quy trình được đóng tự động thông qua giao diện Trình quản lý ngữ cảnh.

Nhiệm vụ 1 đã hoàn thành

Nhiệm vụ 0 xong

Nhiệm vụ 2 thực hiện

Nhiệm vụ 3 thực hiện

Nhiệm vụ 4 thực hiện

  • Đa xử lý hồ bơi chờ tất cả các nhiệm vụ kết thúc trong Python

Làm thế nào để bạn có được kết quả đầu tiên?

Có hai cách tiếp cận chính mà chúng ta có thể sử dụng để có được kết quả từ nhiệm vụ đầu tiên để hoàn thành trong nhóm quy trình.

Họ đang:

  1. Có các nhiệm vụ đặt kết quả của họ trên một hàng đợi chung.
  2. Phát hành các tác vụ sử dụng hàm imap_unordered ().imap_unordered() function.

Hãy cùng nhau xem xét kỹ hơn từng cách tiếp cận.

Một đa xử lý.queue có thể được tạo và chia sẻ giữa tất cả các nhiệm vụ được cấp cho nhóm quy trình.multiprocessing.Queue can be created and shared among all tasks issued to the process pool.

Khi các nhiệm vụ kết thúc, họ có thể đưa kết quả của họ lên hàng đợi.

Quá trình cha mẹ chờ kết quả đầu tiên có thể nhận kết quả đầu tiên có sẵn thông qua hàng đợi được chia sẻ.

Một hàng đợi đa xử lý có thể được tạo ra theo bình thường.

Ví dụ:

.....

# Tạo một hàng đợi được chia sẻ

queue=multiprocessing.Queue()=multiprocessing.Queue()

Chúng tôi không thể chia sẻ hàng đợi trực tiếp với mỗi nhiệm vụ vào nhóm quy trình vì nó sẽ dẫn đến lỗi.

Thay vào đó, chúng tôi có thể chia sẻ hàng đợi với chức năng khởi tạo cho từng quy trình nhân viên trẻ em. Hàng đợi có thể được lưu trữ trong một biến toàn cầu và được cung cấp cho tất cả các nhiệm vụ được thực hiện bởi tất cả các công nhân.

Điều này yêu cầu chúng tôi xác định chức năng khởi tạo nhân viên trẻ em lấy hàng đợi làm đối số, tuyên bố một biến toàn cầu có sẵn cho tất cả các nhiệm vụ được thực hiện bởi người lao động, sau đó lưu trữ hàng đợi trong biến toàn cầu.

Ví dụ:

...

# Tạo một hàng đợi được chia sẻinit_worker(arg_queue):

Chúng tôi không thể chia sẻ hàng đợi trực tiếp với mỗi nhiệm vụ vào nhóm quy trình vì nó sẽ dẫn đến lỗi.# define global variable for each worker

    globalqueueglobalqueue

Thay vào đó, chúng tôi có thể chia sẻ hàng đợi với chức năng khởi tạo cho từng quy trình nhân viên trẻ em. Hàng đợi có thể được lưu trữ trong một biến toàn cầu và được cung cấp cho tất cả các nhiệm vụ được thực hiện bởi tất cả các công nhân.# store queue in global argument

    queue=arg_queuequeue =arg_queue

Điều này yêu cầu chúng tôi xác định chức năng khởi tạo nhân viên trẻ em lấy hàng đợi làm đối số, tuyên bố một biến toàn cầu có sẵn cho tất cả các nhiệm vụ được thực hiện bởi người lao động, sau đó lưu trữ hàng đợi trong biến toàn cầu.

.....

# Tạo một hàng đợi được chia sẻ

pool=Pool(initializer=init_worker,initargs=(queue,))=Pool(initializer=init_worker,initargs=(queue,))

Chúng tôi không thể chia sẻ hàng đợi trực tiếp với mỗi nhiệm vụ vào nhóm quy trình vì nó sẽ dẫn đến lỗi.

  • Thay vào đó, chúng tôi có thể chia sẻ hàng đợi với chức năng khởi tạo cho từng quy trình nhân viên trẻ em. Hàng đợi có thể được lưu trữ trong một biến toàn cầu và được cung cấp cho tất cả các nhiệm vụ được thực hiện bởi tất cả các công nhân.

Điều này yêu cầu chúng tôi xác định chức năng khởi tạo nhân viên trẻ em lấy hàng đợi làm đối số, tuyên bố một biến toàn cầu có sẵn cho tất cả các nhiệm vụ được thực hiện bởi người lao động, sau đó lưu trữ hàng đợi trong biến toàn cầu.put() function and passing the result object.

Ví dụ:

.....

# Tạo một hàng đợi được chia sẻ

queue.put(result).put(result)

Chúng tôi không thể chia sẻ hàng đợi trực tiếp với mỗi nhiệm vụ vào nhóm quy trình vì nó sẽ dẫn đến lỗi.get() function on the queue. This call will block until a result is available.

Ví dụ:

.....

# Tạo một hàng đợi được chia sẻ

result=queue.get()=queue.get()

Chúng tôi không thể chia sẻ hàng đợi trực tiếp với mỗi nhiệm vụ vào nhóm quy trình vì nó sẽ dẫn đến lỗi.

  • Thay vào đó, chúng tôi có thể chia sẻ hàng đợi với chức năng khởi tạo cho từng quy trình nhân viên trẻ em. Hàng đợi có thể được lưu trữ trong một biến toàn cầu và được cung cấp cho tất cả các nhiệm vụ được thực hiện bởi tất cả các công nhân.

Điều này yêu cầu chúng tôi xác định chức năng khởi tạo nhân viên trẻ em lấy hàng đợi làm đối số, tuyên bố một biến toàn cầu có sẵn cho tất cả các nhiệm vụ được thực hiện bởi người lao động, sau đó lưu trữ hàng đợi trong biến toàn cầu.imap_unordered().

# Khởi tạo quy trình công nhân

def init_worker (arg_queue):imap_unordered() function.

Ví dụ:

.....

# Tạo một hàng đợi được chia sẻ

it=pool.imap_unordered(task,items)=pool.imap_unordered(task,items)

Chúng tôi không thể chia sẻ hàng đợi trực tiếp với mỗi nhiệm vụ vào nhóm quy trình vì nó sẽ dẫn đến lỗi.next() function on the returned iterable to get the result from the first task to complete in the process pool.

Thay vào đó, chúng tôi có thể chia sẻ hàng đợi với chức năng khởi tạo cho từng quy trình nhân viên trẻ em. Hàng đợi có thể được lưu trữ trong một biến toàn cầu và được cung cấp cho tất cả các nhiệm vụ được thực hiện bởi tất cả các công nhân.next() function returns the next item in an iterable.

Ví dụ:

.....

# Tạo một hàng đợi được chia sẻ

result=next(it)=next(it)

Chúng tôi không thể chia sẻ hàng đợi trực tiếp với mỗi nhiệm vụ vào nhóm quy trình vì nó sẽ dẫn đến lỗi.imap_unordered() function in the tutorial:

  • Thay vào đó, chúng tôi có thể chia sẻ hàng đợi với chức năng khởi tạo cho từng quy trình nhân viên trẻ em. Hàng đợi có thể được lưu trữ trong một biến toàn cầu và được cung cấp cho tất cả các nhiệm vụ được thực hiện bởi tất cả các công nhân.

Điều này yêu cầu chúng tôi xác định chức năng khởi tạo nhân viên trẻ em lấy hàng đợi làm đối số, tuyên bố một biến toàn cầu có sẵn cho tất cả các nhiệm vụ được thực hiện bởi người lao động, sau đó lưu trữ hàng đợi trong biến toàn cầu.imap_unordered() function and get the first result.

# Khởi tạo quy trình công nhânimap_unordered() function. This will return an iterable that will yield results in the order that the tasks have completed. We can then get the first value from the iterable in order to get the first result.

def init_worker (arg_queue):

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

& nbsp; & nbsp; & nbsp; & nbsp;# xác định biến toàn cầu cho mỗi công nhân

& nbsp; & nbsp; & nbsp; & nbsp;# hàng đợi trong đối số toàn cầu

Sau đó, chúng tôi có thể định cấu hình một nhóm quy trình mới để sử dụng chức năng khởi tạo công nhân của chúng tôi và chuyển hàng đợi làm đối số.random import random

# Tạo một nhóm quy trìnhtime import sleep

Bạn có thể tìm hiểu thêm về việc chia sẻ các biến toàn cầu với tất cả các tác vụ được thực hiện bởi một công nhân trong hướng dẫn này:multiprocessing.pool import Pool

Đa xử lý nhóm Chia sẻ biến toàn cầu với tất cả các công nhân

Các tác vụ sau đó có thể đặt kết quả trên hàng đợi bằng cách gọi hàm put () và truyền đối tượng kết quả.task(identifier):

# Đặt kết quả vào hàng đợi# generate a value

    value=2+random()*10value=2+random()*10

Quá trình chính sau đó có thể lấy kết quả đầu tiên có sẵn thông qua hàm get () trên hàng đợi. Cuộc gọi này sẽ chặn cho đến khi kết quả có sẵn.# report a message

# Nhận kết quả đầu tiênprint(f'Task {identifier} executing with {value}',flush=True)

Bạn có thể tìm hiểu thêm về việc sử dụng hàng đợi đa xử lý trong hướng dẫn:# block for a moment

    sleep(value)sleep(value)

Xếp hàng đa bộ trong python# return the generated value

    return(identifier,value)return(identifier,value)

Một cách tiếp cận khác để có được kết quả đầu tiên từ nhóm quy trình là ban hành các nhiệm vụ bằng cách sử dụng imap_unordered ().

if__name__=='__main__':__name__=='__main__':

Chức năng này sẽ ban hành các nhiệm vụ một cách lười biếng và sẽ trả về một số lượng có thể mang lại kết quả theo thứ tự các nhiệm vụ được hoàn thành, thay vì lệnh mà các nhiệm vụ được ban hành.# create and configure the process pool

Do đó, các tác vụ có thể được ban hành theo bình thường thông qua một cuộc gọi đến hàm imap_unordered ().with Pool()aspool:

# Phát hành nhiệm vụ cho nhóm quy trình# issue many tasks

        it=pool.imap_unordered(task,range(30))it=pool.imap_unordered(task, range(30))

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# get the first result, blocking

        identifier,value=next(it)identifier,value=next(it)

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# Báo cáo kết quả đầu tiên# report the first result

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;print(f'First result: identifier={identifier}, value={value}')

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# chấm dứt# terminate remaining tasks

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;print('Terminating remaining tasks')

Chạy ví dụ đầu tiên tạo ra nhóm quy trình.

Sau đó, nó phát hành tất cả các nhiệm vụ cho nhóm quy trình và trả về một kết quả có thể điều chỉnh được.

Quá trình chính sau đó chặn, chờ kết quả đầu tiên được cung cấp.

Một tập hợp con của các nhiệm vụ bắt đầu thực thi. Mỗi tác vụ tạo ra một số ngẫu nhiên, báo cáo giá trị, khối, sau đó trả về một tuple của giá trị số nguyên và số ngẫu nhiên được tạo.

Một kết quả được nhận bởi quy trình chính và được báo cáo.

Nhóm quy trình và tất cả các nhiệm vụ còn lại sau đó bị chấm dứt mạnh mẽ.

Điều này nhấn mạnh một cách đơn giản để có được kết quả đầu tiên từ nhiều nhiệm vụ trong nhóm quy trình.

Lưu ý, kết quả sẽ khác nhau mỗi khi chương trình được chạy do sử dụng các số ngẫu nhiên.

Nhiệm vụ 0 Thực thi với 2.4591115237324237

Nhiệm vụ 1 Thực hiện với 6.5464709230061455

Nhiệm vụ 2 Thực hiện với 2.847775172423446

Nhiệm vụ 3 Thực hiện với 5.482376922246911

Nhiệm vụ 4 Thực hiện với 7.11178723756704

Nhiệm vụ 5 Thực hiện với 3.6949780247040525

Nhiệm vụ 6 Thực hiện với 5.3101695644764915

Nhiệm vụ 7 Thực hiện với 2.611094260971746

Nhiệm vụ 8 Thực hiện với 4.104337058058016

Kết quả đầu tiên: định danh = 0, giá trị = 2.4591115237324237

Chấm dứt các nhiệm vụ còn lại

Bạn có thể tìm hiểu thêm về cách chờ đợi nhiệm vụ đầu tiên hoàn thành trong hướng dẫn:

  • Nhóm đa xử lý nhận được kết quả đầu tiên

Làm thế nào để bạn tự động thay đổi số lượng quy trình

Bạn không thể tự động tăng hoặc giảm số lượng các quy trình trong một đa xử lý.pool.multiprocessing.Pool.

Số lượng các quy trình được cố định khi đa xử lý.pool được cấu hình trong lệnh gọi đến hàm tạo đối tượng.multiprocessing.Pool is configured in the call to the object constructor.

Ví dụ:

.....

# Định cấu hình một nhóm quy trình

pool=multiprocessing.Pool(4)=multiprocessing.Pool(4)

Làm thế nào để bạn các nhiệm vụ đơn vị và xử lý nhóm?

Bạn có thể trực tiếp kiểm tra các chức năng tác vụ mục tiêu của mình, có thể chế giễu mọi tài nguyên bên ngoài cần thiết.

Bạn có thể kiểm tra đơn vị sử dụng nhóm quy trình với các tác vụ giả không tương tác với các tài nguyên bên ngoài.

Kiểm tra đơn vị các tác vụ và bản thân nhóm quy trình phải được coi là một phần của thiết kế của bạn và có thể yêu cầu kết nối đó với tài nguyên IO có thể định cấu hình để nó có thể bị chế giễu và chức năng tác vụ đích được gọi là nhóm quy trình của bạn có thể định cấu hình để có thể định cấu hình Nó có thể bị chế giễu.

Làm thế nào để bạn so sánh hiệu suất nối tiếp với hiệu suất song song?

Bạn có thể so sánh hiệu suất của chương trình của bạn có và không có nhóm quy trình.

Đây có thể là một bài tập hữu ích để xác nhận rằng việc sử dụng đa xử lý.pool trong chương trình của bạn đã dẫn đến tăng tốc.multiprocessing.Pool in your program has resulted in a speed-up.

Có lẽ cách tiếp cận đơn giản nhất là ghi lại thủ công thời gian bắt đầu và kết thúc của mã của bạn và trừ kết thúc từ thời gian bắt đầu để báo cáo tổng thời gian thực hiện. Sau đó ghi lại thời gian có và không có việc sử dụng nhóm quy trình.

# SuperfastPython.com

# Ví dụ về ghi lại thời gian thực hiện của một chương trình

Thời gian nhập khẩutime

# Ghi lại thời gian bắt đầu

start_time=time.time()=time.time()

# làm việc với hoặc không có nhóm quy trình

# ....

time.sleep(3).sleep(3)

# Ghi lại thời gian kết thúc

end_time=time.time()=time.time()

# Báo cáo thời gian thực hiện

total_time=end_time-start_time=end_time-start_time

print (f'Executing thời gian: {Total_time: .1f} giây. ')(f'Execution time: {total_time:.1f} seconds.')

Sử dụng thời gian thực hiện chương trình trung bình có thể cung cấp thời gian chương trình ổn định hơn so với chạy một lần.

Bạn có thể ghi lại thời gian thực hiện 3 lần trở lên cho chương trình của mình mà không cần nhóm quy trình sau đó tính trung bình khi tổng thời gian chia cho tổng số lần chạy. Sau đó lặp lại bài tập này để tính thời gian trung bình với nhóm quy trình.

Điều này có thể chỉ phù hợp nếu thời gian chạy của chương trình của bạn là vài phút thay vì hàng giờ.

Sau đó, bạn có thể so sánh phiên bản nối tiếp so với song song bằng cách tính toán tốc độ tăng lên nhiều như:

  • Tăng tốc độ nhiều = thời gian nối tiếp / thời gian song song

Ví dụ: nếu lần chạy nối tiếp của một chương trình mất 15 phút (900 giây) và phiên bản song song với đa xử lý.pool mất 5 phút (300 giây), thì tỷ lệ phần trăm sẽ được tính như:multiprocessing.Pool took 5 minutes (300 seconds), then the percentage multiple up would be calculated as:

  • Tăng tốc độ nhiều = thời gian nối tiếp / thời gian song song
  • Ví dụ: nếu lần chạy nối tiếp của một chương trình mất 15 phút (900 giây) và phiên bản song song với đa xử lý.pool mất 5 phút (300 giây), thì tỷ lệ phần trăm sẽ được tính như:
  • Tăng tốc độ nhiều = 900/300

Tăng tốc nhiều = 3multiprocessing.Pool is 3 times faster or 3x faster.

Đó là, phiên bản song song của chương trình với đa xử lý.pool nhanh hơn gấp 3 lần hoặc nhanh hơn gấp 3 lần.

  • Tỷ lệ phần trăm tăng tốc = tăng tốc độ tăng tốc * 100

Trong ví dụ này, phiên bản song song nhanh hơn 300% so với phiên bản nối tiếp.

Làm thế nào để bạn đặt Chunksize trong bản đồ ()?

Hàm bản đồ () và các hàm liên quan như starmap () và imap () trên đa xử lý.pool có một tham số có tên là Chunksize.map() function, and related functions like starmap() and imap() on the multiprocessing.Pool takes a parameter called “chunksize“.

Đối số của người Viking, đối số của người Viking kiểm soát việc ánh xạ các mục trong điều đó được chuyển sang bản đồ () cho các tác vụ được sử dụng trong đa xử lý.pool.chunksize” argument controls the mapping of items in the iterable passed to map() to tasks used in the multiprocessing.Pool.

Ví dụ:

.....

# Áp dụng chức năng cho từng mục trong một số người có thể sử dụng được

forresult inpool.map (nhiệm vụ, vật phẩm, chunksize = 1)result inpool.map(task,items,chunksize=1)

& nbsp; & nbsp; & nbsp; & nbsp;# ...# ...

Giá trị của một có nghĩa là một mục được ánh xạ tới một tác vụ.

Hãy nhớ lại rằng dữ liệu cho từng tác vụ theo các đối số được gửi đến hàm tác vụ mục tiêu và các giá trị được trả về phải được tuần tự hóa bằng Pickle. Điều này xảy ra tự động, nhưng phải chịu một số chi phí tính toán và bộ nhớ, thêm chi phí cho mỗi nhiệm vụ được xử lý bởi nhóm đa xử lý.

Khi có một số lượng lớn các tác vụ hoặc nhiệm vụ tương đối nhanh chóng để tính toán, thì nên điều chỉnh các mục tiêu để tối đa hóa việc nhóm các mục để xử lý các tác vụ nhóm để giảm thiểu chi phí cho mỗi nhiệm vụ và lần lượt giảm thời gian tính toán tổng thể.

Theo mặc định, chunksize được đặt thành không có. Trong trường hợp này, phần Chunksize sẽ không được đặt thành 1 như chúng ta có thể mong đợi, thay vào đó, một đoạn được tính toán được tính toán tự động.chunksize is set to None. In this case, the chunksize will not be set to 1 as we might expect, instead, a chunksize is calculated automatically.

Chúng ta có thể thấy điều này trong mã nguồn cho lớp nhóm:Pool class:

.....

# Áp dụng chức năng cho từng mục trong một số người có thể sử dụng đượcchunksize isNone:

    chunksize,extra=divmod(len(iterable),len(self._pool)*4)chunksize,extra=divmod(len(iterable), len(self._pool)*4)

    ifextra:ifextra:

        chunksize+=1chunksize+=1

forresult inpool.map (nhiệm vụ, vật phẩm, chunksize = 1)divmod() will return the result (quotient) and remainder.

& nbsp; & nbsp; & nbsp; & nbsp;# ...

Giá trị của một có nghĩa là một mục được ánh xạ tới một tác vụ.

  • Hãy nhớ lại rằng dữ liệu cho từng tác vụ theo các đối số được gửi đến hàm tác vụ mục tiêu và các giá trị được trả về phải được tuần tự hóa bằng Pickle. Điều này xảy ra tự động, nhưng phải chịu một số chi phí tính toán và bộ nhớ, thêm chi phí cho mỗi nhiệm vụ được xử lý bởi nhóm đa xử lý.
  • Khi có một số lượng lớn các tác vụ hoặc nhiệm vụ tương đối nhanh chóng để tính toán, thì nên điều chỉnh các mục tiêu để tối đa hóa việc nhóm các mục để xử lý các tác vụ nhóm để giảm thiểu chi phí cho mỗi nhiệm vụ và lần lượt giảm thời gian tính toán tổng thể.
  • Khi có một số lượng lớn các tác vụ hoặc nhiệm vụ tương đối nhanh chóng để tính toán, thì nên điều chỉnh các mục tiêu để tối đa hóa việc nhóm các mục để xử lý các tác vụ nhóm để giảm thiểu chi phí cho mỗi nhiệm vụ và lần lượt giảm thời gian tính toán tổng thể.
  • Theo mặc định, chunksize được đặt thành không có. Trong trường hợp này, phần Chunksize sẽ không được đặt thành 1 như chúng ta có thể mong đợi, thay vào đó, một đoạn được tính toán được tính toán tự động.

Chúng ta có thể thấy điều này trong mã nguồn cho lớp nhóm:

ifchunksize isnone:

DivMod () sẽ trả về kết quả (thương số) và phần còn lại.

Ở đây, chúng tôi đang chia độ dài của đầu vào 4 lần số lượng công nhân trong nhóm.

  • Nếu chúng tôi có 4 quy trình công nhân và một danh sách các mục với 1.000.000 yếu tố, thì phần mềm mặc định sẽ được tính như sau:: The default.
  • Chunksize, Extra = Divmod (1.000.000, 4 * 4): A one-to-one mapping of items to tasks in the pool.
  • Chunksize, Extra = Divmod (1.000.000, 16): Splits all items into a number of worker groups, e.g. one batch of items per process.

Chunksize, thêm = 62500, 0: the (len(items) / number_of_workers) division may need to be rounded as the “chunksize” argument must be a positive integer.

Ví dụ:

.....

# Áp dụng chức năng cho từng mục trong một số người có thể sử dụng được

size=round(len(items)/number_of_workers)=round(len(items)/number_of_workers)

# Áp dụng chức năng cho từng mục trong một số người có thể sử dụng được

forresult inpool.map (nhiệm vụ, vật phẩm, chunksize = 1)result inpool.map(task,items,chunksize=size)

& nbsp; & nbsp; & nbsp; & nbsp;# ...# ...

Giá trị của một có nghĩa là một mục được ánh xạ tới một tác vụ.

Hãy nhớ lại rằng dữ liệu cho từng tác vụ theo các đối số được gửi đến hàm tác vụ mục tiêu và các giá trị được trả về phải được tuần tự hóa bằng Pickle. Điều này xảy ra tự động, nhưng phải chịu một số chi phí tính toán và bộ nhớ, thêm chi phí cho mỗi nhiệm vụ được xử lý bởi nhóm đa xử lý.

Khi có một số lượng lớn các tác vụ hoặc nhiệm vụ tương đối nhanh chóng để tính toán, thì nên điều chỉnh các mục tiêu để tối đa hóa việc nhóm các mục để xử lý các tác vụ nhóm để giảm thiểu chi phí cho mỗi nhiệm vụ và lần lượt giảm thời gian tính toán tổng thể.

Theo mặc định, chunksize được đặt thành không có. Trong trường hợp này, phần Chunksize sẽ không được đặt thành 1 như chúng ta có thể mong đợi, thay vào đó, một đoạn được tính toán được tính toán tự động.

  1. Chúng ta có thể thấy điều này trong mã nguồn cho lớp nhóm:
  2. ifchunksize isnone:

DivMod () sẽ trả về kết quả (thương số) và phần còn lại.

Ở đây, chúng tôi đang chia độ dài của đầu vào 4 lần số lượng công nhân trong nhóm.

Nếu chúng tôi có 4 quy trình công nhân và một danh sách các mục với 1.000.000 yếu tố, thì phần mềm mặc định sẽ được tính như sau:

Chunksize, Extra = Divmod (1.000.000, 4 * 4)

Chunksize, Extra = Divmod (1.000.000, 16)apply_async() function that returns a ResultAsync.

.....

# Áp dụng chức năng cho từng mục trong một số người có thể sử dụng được

result=pool.apply_async(...)=pool.apply_async(...)

forresult inpool.map (nhiệm vụ, vật phẩm, chunksize = 1)

Ví dụ:

.....

# Áp dụng chức năng cho từng mục trong một số người có thể sử dụng được

ifresult.get()>1.0:result.get()>1.0:

forresult inpool.map (nhiệm vụ, vật phẩm, chunksize = 1)# issue a follow-up task

    pool.apply_async(...)pool.apply_async(...)

& nbsp; & nbsp; & nbsp; & nbsp;# ...

Giá trị của một có nghĩa là một mục được ánh xạ tới một tác vụ.

Hãy nhớ lại rằng dữ liệu cho từng tác vụ theo các đối số được gửi đến hàm tác vụ mục tiêu và các giá trị được trả về phải được tuần tự hóa bằng Pickle. Điều này xảy ra tự động, nhưng phải chịu một số chi phí tính toán và bộ nhớ, thêm chi phí cho mỗi nhiệm vụ được xử lý bởi nhóm đa xử lý.

Khi có một số lượng lớn các tác vụ hoặc nhiệm vụ tương đối nhanh chóng để tính toán, thì nên điều chỉnh các mục tiêu để tối đa hóa việc nhóm các mục để xử lý các tác vụ nhóm để giảm thiểu chi phí cho mỗi nhiệm vụ và lần lượt giảm thời gian tính toán tổng thể.

Theo mặc định, chunksize được đặt thành không có. Trong trường hợp này, phần Chunksize sẽ không được đặt thành 1 như chúng ta có thể mong đợi, thay vào đó, một đoạn được tính toán được tính toán tự động.

Như vậy, chúng tôi có thể trực tiếp phát hành các tác vụ tiếp theo từ chức năng gọi lại.

Ví dụ:

# chức năng gọi lại kết quả

Def results_callback (result):result_callback(result):

& nbsp; & nbsp; & nbsp; & nbsp;# Kiểm tra kết quả của một nhiệm vụ đã phát hành# check the result of an issued task

    ifresult.get()>1.0:ifresult.get()>1.0:

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# issue a follow-up task

        pool.apply_async(...)pool.apply_async(...)

Hàm gọi lại có thể được chỉ định khi ban hành các tác vụ trong quy trình chính thông qua đối số gọi lại của Cameron.callback” argument.

Ví dụ:

# chức năng gọi lại kết quả..

Def results_callback (result):

result=pool.apply_async(...,callback=result_callback)=pool.apply_async(...,callback=result_callback)

& nbsp; & nbsp; & nbsp; & nbsp;# Kiểm tra kết quả của một nhiệm vụ đã phát hành

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

Hàm gọi lại có thể được chỉ định khi ban hành các tác vụ trong quy trình chính thông qua đối số gọi lại của Cameron.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

...

# ban hành một nhiệm vụ với một cuộc gọi lại kết quả

Chúng ta có thể khám phá cách tự động phát hành các tác vụ tiếp theo bằng cách sử dụng chức năng gọi lại.random import random

Điều này có thể đạt được bằng cách xác định chức năng gọi lại xử lý kết quả từ các tác vụ vòng một và các vấn đề theo dõi các tác vụ theo nhóm quy trình. Quá trình chính chỉ chịu trách nhiệm ban hành các nhiệm vụ vòng đầu tiên.time import sleep

Một ví dụ hoàn chỉnh để chứng minh điều này được liệt kê dưới đây.multiprocessing.pool import Pool

# SuperfastPython.com

# Ví dụ về việc tự động phát hành một tác vụ tiếp theo với một cuộc gọi lại kết quảresult_callback(result_iterator):

từ nhập ngẫu nhiên ngẫu nhiên# unpack result

    fori,vinresult_iterator:fori,vinresult_iterator:

từ thời gian nhập vào giấc ngủ# check result

        ifv>0.5:ifv>0.5:

từ đa bộ xử lý.pool Pool# issue a follow-up task

            _=pool.apply_async(task2,args=(i,v))_= pool.apply_async(task2,args=(i,v))

# Xử lý kết quả của nhiệm vụ (trong quy trình chính)

Def results_callback (result_iterator):task2(identifier,result):

& nbsp; & nbsp; & nbsp; & nbsp;# giải nén kết quả# generate a random number

    value=random()value=random()

& nbsp;# block for a moment

    sleep(value)sleep(value)

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# report result

# Nhiệm vụ được thực hiện trong một quy trình công nhânprint(f'>>{identifier} with {result}, generated {value}',flush=True)

DEF TASK2 (Định danh, Kết quả):# return result

    return(identifier,result,value)return(identifier,result,value)

# Xử lý kết quả của nhiệm vụ (trong quy trình chính)

Def results_callback (result_iterator):task1(identifier):

& nbsp; & nbsp; & nbsp; & nbsp;# giải nén kết quả# generate a random number

    value=random()value=random()

& nbsp;# block for a moment

    sleep(value)sleep(value)

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;# report result

# Nhiệm vụ được thực hiện trong một quy trình công nhânprint(f'>{identifier} generated {value}',flush=True)

DEF TASK2 (Định danh, Kết quả):# return result

    return(identifier,value)return (identifier,value)

& nbsp; & nbsp; & nbsp; & nbsp;# tạo một số ngẫu nhiên

if__name__=='__main__':__name__=='__main__':

& nbsp; & nbsp; & nbsp; & nbsp;# block trong giây lát# create and configure the process pool

& nbsp; & nbsp; & nbsp; & nbsp;# kết quả báo cáowith Pool() aspool:

& nbsp; & nbsp; & nbsp; & nbsp; print (f '>> {định danh} với {result}, được tạo {value}', flush = true)# issue tasks asynchronously to the process pool

        result=pool.map_async(task1,range(10),callback=result_callback)result=pool.map_async(task1, range(10),callback=result_callback)

& nbsp; & nbsp; & nbsp; & nbsp;# return kết quả# wait for issued tasks to complete

        result.wait()result.wait()

DEF TASK1 (Định danh):# close the pool

        pool.close()pool.close()

& nbsp; & nbsp; & nbsp; & nbsp; print (f '> {định danh} đã tạo {value}', flush = true)# wait for all issued tasks to complete

        pool.join()pool.join()

# Bảo vệ điểm vào# all done

& nbsp; & nbsp; & nbsp; & nbsp;# tạo và định cấu hình nhóm quy trìnhprint('All done.')

& nbsp; & nbsp; & nbsp; & nbsp; với pool () aspool:

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & NBSP;task1() are issued as tasks to the process pool and an AsyncResult is returned. The main process then blocks waiting for all first-round tasks to complete.

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

& nbsp; & nbsp; & nbsp; & nbsp;# tất cả đã hoàn thành

& nbsp; & nbsp; & nbsp; & nbsp; in ('tất cả đã hoàn thành.')

Chạy ví dụ đầu tiên tạo và bắt đầu nhóm quy trình với cấu hình mặc định.

Điều này nhấn mạnh cách chúng ta có thể tự động phát hành các nhiệm vụ tiếp theo cho nhóm quy trình từ quy trình chính.

> 3 được tạo 0,026053470123407307

> 5 được tạo 0.10861107021623373

> 1 được tạo 0,283776825109049

> 2 được tạo 0,3812563597749301

> 0 được tạo 0,47683270636655106

> 4 được tạo 0,5622089438427635

> 6 được tạo 0,62617584793209

> 7 được tạo 0,7745782124217487

> 8 được tạo 0,9132687159744634

> 9 được tạo 0,9283828682129988

>> 7 với 0,7745782124217487, được tạo 0,07060930439614588

>> 6 với 0,62617584793209, được tạo 0,155765787897853

>> 4 với 0,5622089438427635, được tạo 0,7745894701213474

>> 8 với 0,9132687159744634, được tạo 0,8280977095949135

>> 9 với 0,9283828682129988, được tạo 0,9937548669689297

Tất cả đã được làm xong.

Bạn có thể tìm hiểu thêm về cách phát hành một nhiệm vụ tiếp theo trong hướng dẫn:

  • Các nhiệm vụ theo dõi nhóm đa xử lý trong Python

Làm thế nào để bạn thể hiện sự tiến bộ của tất cả các nhiệm vụ?

Chúng ta có thể hiển thị tiến trình của các tác vụ trong nhóm quy trình bằng cách sử dụng chức năng gọi lại.

Điều này có thể đạt được bằng cách ban hành các tác vụ không đồng bộ vào nhóm quy trình, chẳng hạn như thông qua hàm application_async () và chỉ định chức năng gọi lại thông qua đối số gọi lại của Cameron.apply_async() function and specifying a callback function via the “callback” argument.

Ví dụ:

.....

# Phát hành một nhiệm vụ cho nhóm quy trình

pool.apply_async(task,callback=progress).apply_async(task,callback=progress)

Hàm gọi lại tùy chỉnh của chúng tôi sau đó sẽ được gọi sau mỗi nhiệm vụ trong nhóm quy trình được hoàn thành.

Sau đó, chúng ta có thể thực hiện một số hành động để hiển thị tiến trình của các tác vụ đã hoàn thành trong hàm gọi lại, chẳng hạn như in dấu chấm ra tiêu chuẩn.

Ví dụ:

...

# Phát hành một nhiệm vụ cho nhóm quy trìnhprogress(results):

    print('.',end='',flush=True)print('.',end='',flush=True)

Hàm gọi lại tùy chỉnh của chúng tôi sau đó sẽ được gọi sau mỗi nhiệm vụ trong nhóm quy trình được hoàn thành.

Sau đó, chúng ta có thể thực hiện một số hành động để hiển thị tiến trình của các tác vụ đã hoàn thành trong hàm gọi lại, chẳng hạn như in dấu chấm ra tiêu chuẩn.

# Chỉ báo tiến trình cho các tác vụ trong nhóm quy trình

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

Tiến trình def (kết quả):

Chúng ta có thể khám phá cách hiển thị tiến trình của các nhiệm vụ được phát hành cho nhóm quy trình.

Trong ví dụ này, chúng tôi sẽ xác định một nhiệm vụ sẽ chặn cho một phần nhỏ thứ hai. Sau đó chúng tôi sẽ phát hành nhiều nhiệm vụ này cho nhóm quy trình. Một cuộc gọi lại sẽ được gọi khi mỗi nhiệm vụ kết thúc và sẽ in một thông báo để hiển thị tiến trình của các nhiệm vụ khi chúng được hoàn thành.time import sleep

Một ví dụ hoàn chỉnh để chứng minh điều này được liệt kê dưới đây.random import random

# SuperfastPython.commultiprocessing.pool import Pool

...

# Phát hành một nhiệm vụ cho nhóm quy trìnhprogress(results):

    print('.',end='',flush=True)print('.',end='',flush=True)

Hàm gọi lại tùy chỉnh của chúng tôi sau đó sẽ được gọi sau mỗi nhiệm vụ trong nhóm quy trình được hoàn thành.

Sau đó, chúng ta có thể thực hiện một số hành động để hiển thị tiến trình của các tác vụ đã hoàn thành trong hàm gọi lại, chẳng hạn như in dấu chấm ra tiêu chuẩn.task():

# Chỉ báo tiến trình cho các tác vụ trong nhóm quy trình# generate a random value

    value=random()value=random()

Tiến trình def (kết quả):# block for a moment

    sleep(value)sleep(value)

Chúng ta có thể khám phá cách hiển thị tiến trình của các nhiệm vụ được phát hành cho nhóm quy trình.

if__name__=='__main__': __name__=='__main__':

Trong ví dụ này, chúng tôi sẽ xác định một nhiệm vụ sẽ chặn cho một phần nhỏ thứ hai. Sau đó chúng tôi sẽ phát hành nhiều nhiệm vụ này cho nhóm quy trình. Một cuộc gọi lại sẽ được gọi khi mỗi nhiệm vụ kết thúc và sẽ in một thông báo để hiển thị tiến trình của các nhiệm vụ khi chúng được hoàn thành.# create and configure the process pool

Một ví dụ hoàn chỉnh để chứng minh điều này được liệt kê dưới đây.with Pool()aspool:

# SuperfastPython.com# issue many tasks asynchronously to the process pool

        results=[pool.apply_async(task,callback=progress)for_inrange(20)]results=[pool.apply_async(task,callback=progress)for_in range(20)]

# Ví dụ về việc hiển thị tiến trình trong nhóm quy trình với các nhiệm vụ riêng biệt# close the pool

        pool.close()pool.close()

từ thời gian nhập vào giấc ngủ# wait for all issued tasks to complete

        pool.join()pool.join()

từ nhập ngẫu nhiên ngẫu nhiên# report all done

từ đa bộ xử lý.pool Poolprint('\nDone!')

# Nhiệm vụ được thực hiện trong một quy trình công nhân

nhiệm vụ def ():

& nbsp; & nbsp; & nbsp; & nbsp;# tạo một giá trị ngẫu nhiên

& nbsp; & nbsp; & nbsp; & nbsp;# block trong giây lát

# Bảo vệ điểm vào

& nbsp; & nbsp; & nbsp; & nbsp;# tạo và định cấu hình nhóm quy trình

& nbsp; & nbsp; & nbsp; & nbsp; với pool () aspool:

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

Done!

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

  • & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

& nbsp; & nbsp; & nbsp; & nbsp;# báo cáo tất cả đã hoàn thành

& nbsp; & nbsp; & nbsp; & nbsp; in ('\ ndone!'))

Chạy ví dụ đầu tiên tạo ra nhóm quy trình.RuntimeError when starting a new Process in Python.

Sau đó, 20 nhiệm vụ được phát hành cho nhóm, mỗi lần một.

Quá trình chính sau đó đóng nhóm quy trình và các khối chờ tất cả các nhiệm vụ được cấp hoàn thành.

Mỗi khối nhiệm vụ cho một phần của một giây và kết thúc.

Khi mỗi tác vụ kết thúc, hàm gọi lại được gọi, in dấu chấm.

Các dấu chấm tích lũy trên đầu ra tiêu chuẩn, cho thấy tiến trình của tất cả các nhiệm vụ được phát hành.

Khi tất cả các tác vụ kết thúc, quá trình chính tiếp tục và báo cáo một tin nhắn cuối cùng.

....................

freeze_support()

...

# Phát hành một nhiệm vụ cho nhóm quy trình

Hàm gọi lại tùy chỉnh của chúng tôi sau đó sẽ được gọi sau mỗi nhiệm vụ trong nhóm quy trình được hoàn thành.

Điều này sẽ xảy ra trên Windows và MacOS trong đó phương thức bắt đầu mặc định là ‘Spawn. Nó cũng có thể xảy ra khi bạn định cấu hình chương trình của mình để sử dụng phương thức bắt đầu ‘Spawn‘ trên các nền tảng khác.spawn‘. It may also happen when you configure your program to use the ‘spawn‘ start method on other platforms.

Bạn sẽ nhận được thời gian chạy này khi sử dụng Multiprocessing.pool và không bảo vệ điểm nhập khi sử dụng phương thức bắt đầu ‘Spawn.RuntimeError when using the multiprocessing.Pool and do not protect the entry point when using the ‘spawn’ start method.

Việc sửa chữa liên quan đến việc kiểm tra xem mã có chạy trong môi trường cấp cao nhất và chỉ sau đó, hãy cố gắng bắt đầu một quy trình mới.

Đây là một thực hành tốt nhất.

Thành ngữ cho bản sửa lỗi này, như đã nêu trong thông báo của RunTimeError, là sử dụng một câu chuyện if và kiểm tra xem tên của mô-đun bằng với chuỗi ‘__main__.RuntimeError, is to use an if-statement and check if the name of the module is equal to the string ‘__main__‘.

Ví dụ:

.....

# Kiểm tra môi trường cấp cao nhất

if__name__=='__main__':__name__=='__main__':

& nbsp; & nbsp; & nbsp; & nbsp;# ...# ...

Đây được gọi là bảo vệ điểm vào điểm vào của chương trình.

Nhớ lại, __name__ là một biến đề cập đến tên của mô -đun thực thi mã hiện tại.__name__ is a variable that refers to the name of the module executing the current code.

Ngoài ra, hãy nhớ lại rằng ‘__main__ là tên của môi trường cấp cao nhất được sử dụng để thực hiện chương trình Python.__main__‘ is the name of the top-level environment used to execute a Python program.

Sử dụng một câu chuyện IF để kiểm tra xem mô-đun có phải là môi trường cấp cao nhất không và chỉ bắt đầu các quy trình con trong khối đó sẽ giải quyết thời gian chạy.RuntimeError.

Điều đó có nghĩa là nếu tệp python được nhập, thì mã được bảo vệ bởi if-satatement sẽ không chạy. Nó sẽ chỉ chạy khi tệp Python được chạy trực tiếp, ví dụ: là môi trường cấp cao nhất.

Thành ngữ if-statement là bắt buộc, ngay cả khi điểm nhập của chương trình gọi một hàm tự bắt đầu quy trình con.

Bạn có thể tìm hiểu thêm về việc bảo vệ điểm nhập khi sử dụng đa xử lý trong hướng dẫn:

  • Thêm nếu __name__ == ‘__main__, khi sinh sản một quá trình con

Tôi có cần gọi Freeze_support () không?

Các chương trình Python có thể được chuyển đổi thành một Windows có thể thực thi.

Trong quá trình chuyển đổi, các chương trình Python bị đóng băng. Nếu các chương trình này cố gắng bắt đầu các quy trình mới, nó sẽ dẫn đến RuntimEError.

Do đó, nếu bạn có ý định đóng băng chương trình của bạn (ví dụ: chuyển đổi nó thành một windows có thể thực thi), bạn phải thêm hỗ trợ Freeze.

Điều này có thể đạt được bằng cách gọi hàm freeze_support () là dòng đầu tiên của chương trình của bạn, như là dòng đầu tiên sau khi kiểm tra điểm nhập được bảo vệ; Ví dụ:freeze_support() function as the first line of your program, such the first line after checking for the protected entry point; for example:

# Điểm vào được bảo vệ

if__name__=='__main__':__name__=='__main__':

    freeze_support()freeze_support()

& nbsp; & nbsp; & nbsp; & nbsp;# ...# ...

Đây được gọi là bảo vệ điểm vào điểm vào của chương trình.

  • Nhớ lại, __name__ là một biến đề cập đến tên của mô -đun thực thi mã hiện tại.

Ngoài ra, hãy nhớ lại rằng ‘__main__ là tên của môi trường cấp cao nhất được sử dụng để thực hiện chương trình Python.

Sử dụng một câu chuyện IF để kiểm tra xem mô-đun có phải là môi trường cấp cao nhất không và chỉ bắt đầu các quy trình con trong khối đó sẽ giải quyết thời gian chạy.

Điều đó có nghĩa là nếu tệp python được nhập, thì mã được bảo vệ bởi if-satatement sẽ không chạy. Nó sẽ chỉ chạy khi tệp Python được chạy trực tiếp, ví dụ: là môi trường cấp cao nhất.map(), starmap(), imap(), imap_unordered(), or apply() it does create an AsyncResult object for each task.

Thành ngữ if-statement là bắt buộc, ngay cả khi điểm nhập của chương trình gọi một hàm tự bắt đầu quy trình con.AsyncResult when issuing tasks to the process pool using the functions:

  • apply_async()
  • map_async()
  • starmap_async()

Bạn có thể tìm hiểu thêm về việc bảo vệ điểm nhập khi sử dụng đa xử lý trong hướng dẫn:

Thêm nếu __name__ == ‘__main__, khi sinh sản một quá trình conmultiprocessing.pool.Pool cannot be shared with child processes directly.

Tôi có cần gọi Freeze_support () không?

Các chương trình Python có thể được chuyển đổi thành một Windows có thể thực thi.NotImplementedError:

Trong quá trình chuyển đổi, các chương trình Python bị đóng băng. Nếu các chương trình này cố gắng bắt đầu các quy trình mới, nó sẽ dẫn đến RuntimEError.

Do đó, nếu bạn có ý định đóng băng chương trình của bạn (ví dụ: chuyển đổi nó thành một windows có thể thực thi), bạn phải thêm hỗ trợ Freeze.

Điều này có thể đạt được bằng cách gọi hàm freeze_support () là dòng đầu tiên của chương trình của bạn, như là dòng đầu tiên sau khi kiểm tra điểm nhập được bảo vệ; Ví dụ:

# Điểm vào được bảo vệ

Ví dụ:

  • ...
  • # Kiểm tra môi trường cấp cao nhất
  • & nbsp; & nbsp; & nbsp; & nbsp;# ...

Đây được gọi là bảo vệ điểm vào điểm vào của chương trình.

Nhớ lại, __name__ là một biến đề cập đến tên của mô -đun thực thi mã hiện tại.

  • Ngoài ra, hãy nhớ lại rằng ‘__main__ là tên của môi trường cấp cao nhất được sử dụng để thực hiện chương trình Python.
  • Sử dụng một câu chuyện IF để kiểm tra xem mô-đun có phải là môi trường cấp cao nhất không và chỉ bắt đầu các quy trình con trong khối đó sẽ giải quyết thời gian chạy.
  • Điều đó có nghĩa là nếu tệp python được nhập, thì mã được bảo vệ bởi if-satatement sẽ không chạy. Nó sẽ chỉ chạy khi tệp Python được chạy trực tiếp, ví dụ: là môi trường cấp cao nhất.

Thành ngữ if-statement là bắt buộc, ngay cả khi điểm nhập của chương trình gọi một hàm tự bắt đầu quy trình con.

Bạn có thể tìm hiểu thêm về việc bảo vệ điểm nhập khi sử dụng đa xử lý trong hướng dẫn:

Thêm nếu __name__ == ‘__main__, khi sinh sản một quá trình conmultiprocessing.Manager provides a way to create a centralized version of a Python object hosted on a server process.

Tôi có cần gọi Freeze_support () không?

Các chương trình Python có thể được chuyển đổi thành một Windows có thể thực thi.

Trong quá trình chuyển đổi, các chương trình Python bị đóng băng. Nếu các chương trình này cố gắng bắt đầu các quy trình mới, nó sẽ dẫn đến RuntimEError.multiprocessing.Manager is a useful way to centralize a synchronization primitive like a multiprocessing.pool.Pool shared among multiple processes, such as worker processes in the pool itself.

Trước tiên chúng ta có thể tạo một đa xử lý. Người quản lý bằng giao diện Trình quản lý ngữ cảnh.multiprocessing.Manager using the context manager interface.

Ví dụ:

.....

# Tạo người quản lý

với người quản lý () asmanager:Manager()asmanager:

& nbsp; & nbsp; & nbsp; & nbsp;# ...# ...

Sau đó, chúng ta có thể tạo một đối tượng đa xử lý được chia sẻ.pool.pool bằng cách sử dụng trình quản lý.multiprocessing.pool.Pool object using the manager.

Điều này sẽ trả về một đối tượng proxy cho đối tượng đa xử lý.pool.pool trong quy trình trình quản lý mà chúng ta có thể chia sẻ giữa các quy trình nhân viên trẻ em hoặc gián tiếp.multiprocessing.pool.Pool object in the manager process that we can share among child worker processes directly or indirectly.

Ví dụ:

.....

# Tạo người quản lý

pool=manager.Pool()=manager.Pool()

với người quản lý () asmanager:multiprocessing.pool.Pool can then be passed to a child worker initialization function or to a task function as an argument to be executed by worker processes.

& nbsp; & nbsp; & nbsp; & nbsp;# ...

Sau đó, chúng ta có thể tạo một đối tượng đa xử lý được chia sẻ.pool.pool bằng cách sử dụng trình quản lý.

Điều này sẽ trả về một đối tượng proxy cho đối tượng đa xử lý.pool.pool trong quy trình trình quản lý mà chúng ta có thể chia sẻ giữa các quy trình nhân viên trẻ em hoặc gián tiếp.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

# Tạo một đối tượng được chia sẻ thông qua Trình quản lý

Proxy cho đa xử lý.pool.pool sau đó có thể được chuyển đến chức năng khởi tạo nhân viên con hoặc chức năng tác vụ như một đối số được thực hiện bởi các quy trình của công nhân.

Chúng ta có thể khám phá cách chúng ta có thể chia sẻ một nhóm quy trình với các quy trình con bằng cách sử dụng người quản lý.multiprocessing import Manager

Trong ví dụ này, chúng tôi sẽ xác định một chức năng tác vụ tùy chỉnh lấy một nhóm quy trình làm đối số và báo cáo chi tiết của nó. Sau đó, chúng tôi sẽ ban hành nhiệm vụ từ quy trình chính không đồng bộ và thông qua nhóm quy trình như một đối số. Trong quy trình chính, chúng tôi sẽ tạo một nhóm quy trình bằng cách sử dụng đa xử lý.Manager. Điều này sẽ tạo ra một phiên bản tập trung của nhóm quy trình đang chạy trong một quy trình máy chủ và trả về các đối tượng proxy cho nhóm quy trình mà chúng ta có thể chia sẻ giữa các quy trình con.

Ví dụ dưới đây cho thấy điều này.handler(error):

    print(error,flush=True)print(error, flush=True)

# SuperfastPython.com

# Ví dụ về việc chia sẻ một nhóm quy trình giữa các quy trìnhtask(pool):

từ Trình quản lý nhập khẩu đa xử lý# report a message

# chức năng gọi lại lỗiprint(f'Pool Details: {pool}')

DEF Handler (lỗi):

if__name__=='__main__': __name__=='__main__':

# Nhiệm vụ được thực hiện trong một quy trình công nhân# create a manager

nhiệm vụ def (nhóm):with Manager()asmanager:

& nbsp; & nbsp; & nbsp; & nbsp;# báo cáo một tin nhắn# create and configure the process pool

& nbsp; & nbsp; & nbsp; & nbsp; in (chi tiết f'pool: {pool} '))with manager.Pool()aspool:

# Bảo vệ điểm vào# issue a task to the process pool

            pool.apply_async(task,args=(pool,),error_callback=handler)pool.apply_async(task, args=(pool,),error_callback=handler)

& nbsp; & nbsp; & nbsp; & nbsp;# tạo một trình quản lý# close the pool

            pool.close()pool.close()

& nbsp; & nbsp; & nbsp; & nbsp; với trình quản lý () asmanager:# wait for all issued tasks to complete

            pool.join()pool.join()

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp;

Chạy ví dụ đầu tiên tạo ra nhóm quy trình.

Sau đó, nó phát hành nhiệm vụ không đồng bộ. Quá trình chính sau đó đóng nhóm quy trình và chờ tất cả các nhiệm vụ được cấp hoàn thành.

Nhiệm vụ thực hiện bình thường và báo cáo các chi tiết của nhóm quy trình.

Trong trường hợp này, nhóm được truy cập thông qua đối tượng proxy mà không gặp vấn đề gì và các chi tiết của nhóm được báo cáo. Nó được đóng lại và được tạo ra với 8 quy trình lao động trẻ em.

Lưu ý, cấu hình mặc định cụ thể của nhóm quy trình trên hệ thống của bạn có thể khác nhau.

Nhiệm vụ hoàn thành và quy trình chính được thực hiện, đầu tiên chấm dứt nhóm quy trình, sau đó chấm dứt người quản lý.

Điều này nhấn mạnh cách chúng tôi có thể chia sẻ một nhóm quy trình với các quy trình nhân viên trẻ em một cách gián tiếp bằng cách sử dụng người quản lý.Lock and RLock, as well as Semaphore, Barrier, Event, and Condition.

Chi tiết hồ bơi:

Làm thế nào để bạn sử dụng các nguyên thủy đồng bộ hóa (khóa, semaphore, v.v.) ở công nhân?multiprocessing.Lock.

Các nguyên thủy đồng bộ hóa không thể được chia sẻ trực tiếp với công nhân trong nhóm quy trình.multiprocessing.Lock instance with worker processes indirectly, they are:

  • Điều này là do các nguyên thủy đồng bộ hóa không thể được tuần tự hóa, ví dụ: Dưa chua, đó là một yêu cầu khi chuyển dữ liệu cho các quy trình của nhân viên trẻ em.
  • Nhớ lại, các nguyên thủy đồng bộ hóa bao gồm các khóa mutex như khóa và rlock, cũng như semaphore, rào cản, sự kiện và điều kiện.
  • Thay vào đó, chúng ta phải sử dụng một cách giải quyết khi sử dụng các nguyên thủy đồng bộ hóa trong nhóm quy trình.fork‘ start method, storing it in a global variable, then having child processes inherit the variable.

Các cách giải quyết tương tự sẽ hoạt động với tất cả các nguyên thủy đồng bộ hóa, nhưng chúng ta có thể chứng minh nó với đa xử lý.lock.fork‘ start method will work, and provides an easy way to share a lock with child worker processes.

Có lẽ có ba cách chúng ta có thể chia sẻ một phiên bản đa bộ xử lý với các quy trình của công nhân một cách gián tiếp, chúng là:fork‘ start method is not available on all platforms, e.g. it cannot be used on Windows.

Thay phiên, nếu chúng ta ngây thơ vượt qua một bộ xử lý.multiprocessing.Lock as an argument when initializing the process pool or in a task executed by the process pool, it will fail with an error, such as:

Các đối tượng khóa chỉ nên được chia sẻ giữa các quy trình thông qua kế thừa

Thay vào đó, chúng ta phải sử dụng một đa xử lý.multiprocessing.Manager.

Một đa xử lý. Người quản lý tạo ra một quy trình và chịu trách nhiệm quản lý một phiên bản tập trung của một đối tượng. Sau đó, nó cung cấp các đối tượng proxy có thể được sử dụng trong các quy trình khác luôn cập nhật với đối tượng tập trung duy nhất.multiprocessing.Manager creates a process and is responsible for managing a centralized version of an object. It then provides proxy objects that can be used in other processes that keep up-to-date with the single centralized object.

Như vậy, sử dụng đa xử lý. Người quản lý là một cách hữu ích để tập trung một nguyên thủy đồng bộ hóa như đa xử lý.lock được chia sẻ giữa nhiều quy trình của công nhân.multiprocessing.Manager is a useful way to centralize a synchronization primitive like a multiprocessing.Lock shared among multiple worker processes.

Trước tiên chúng ta có thể tạo một đa xử lý. Người quản lý bằng giao diện Trình quản lý ngữ cảnh.multiprocessing.Manager using the context manager interface.

Ví dụ:

.....

# Tạo người quản lý

với người quản lý () asmanager:Manager()asmanager:

& nbsp; & nbsp; & nbsp; & nbsp;# ...# ...

Sau đó, chúng ta có thể tạo một đối tượng đa xử lý được chia sẻ bằng cách sử dụng trình quản lý.multiprocessing.Lock object using the manager.

Điều này sẽ trả về một đối tượng proxy cho đối tượng đa xử lý.multiprocessing.Lock object in the manager process that we can share among child worker processes directly or indirectly.

Ví dụ:

.....

# Tạo người quản lý

lock=manager.Lock()=manager.Lock()

với người quản lý () asmanager:multiprocessing.Lock can then be passed to a child worker initialization function or to a task function executed by worker processes.

& nbsp; & nbsp; & nbsp; & nbsp;# ...

Sau đó, chúng ta có thể tạo một đối tượng đa xử lý được chia sẻ bằng cách sử dụng trình quản lý.

  • Điều này sẽ trả về một đối tượng proxy cho đối tượng đa xử lý.
  • # Tạo một đối tượng được chia sẻ thông qua Trình quản lý
  • Proxy cho đa xử lý.lock sau đó có thể được chuyển đến chức năng khởi tạo nhân viên con hoặc chức năng tác vụ được thực hiện bởi các quy trình của công nhân.
  • Đây là cách tiếp cận ưa thích và sẽ hoạt động trên tất cả các nền tảng với tất cả các nguyên thủy đồng bộ hóa.
  • Bạn có thể tìm hiểu thêm về cách sử dụng các nguyên thủy đồng bộ hóa trong các quy trình của công nhân trẻ em trong các hướng dẫn:

Sử dụng khóa trong nhóm đa xử lý

Sử dụng semaphore trong nhóm đa xử lýmultiprocessing.Pool may not be the best solution for all concurrency problems in your program.

Sử dụng một sự kiện trong nhóm đa xử lý

Sử dụng một biến điều kiện trong nhóm đa xử lý

Sử dụng một rào cản trong nhóm quy trình

Phản đối phổ biến đối với việc sử dụng nhóm đa xử lý

Đa xử lý.pool có thể không phải là giải pháp tốt nhất cho tất cả các vấn đề đồng thời trong chương trình của bạn.multiprocessing.Pool class.

Điều đó đang được nói, cũng có thể có một số hiểu lầm đang ngăn bạn sử dụng đầy đủ và tốt nhất các khả năng của nhóm đa xử lý trong chương trình của bạn.

Trong phần này, chúng tôi xem xét một số phản đối phổ biến mà các nhà phát triển thấy khi xem xét sử dụng nhóm đa xử lý trong mã của họ

Hãy để lặn trong.

Điều gì về khóa phiên dịch toàn cầu (GIL)?

GIL thường không liên quan khi sử dụng các quy trình như lớp quy trình hoặc lớp đa xử lý.pool.

Khóa thông dịch viên toàn cầu, hoặc ngắn hoàn toàn là Gil, là một quyết định thiết kế với trình thông dịch Python tham chiếu.threading.Thread class and the multiprocessing.pool.ThreadPool. It is not a consideration when using the multiprocessing Pool (unless you use additional threads within each task).

Nó đề cập đến thực tế là việc triển khai trình thông dịch Python sử dụng khóa chính để ngăn chặn nhiều hơn một hướng dẫn Python thực thi cùng một lúc.

  • Điều này ngăn chặn nhiều hơn một luồng thực thi trong các chương trình Python, cụ thể trong mỗi quy trình Python, đó là mỗi trường hợp của trình thông dịch Python.

Việc thực hiện GIL có nghĩa là các luồng python có thể đồng thời, nhưng không thể chạy song song. Nhớ lại rằng đồng thời có nghĩa là có nhiều nhiệm vụ có thể được tiến hành cùng một lúc, song song có nghĩa là nhiều hơn một nhiệm vụ thực sự thực hiện cùng một lúc. Các nhiệm vụ song song là đồng thời ;, các nhiệm vụ đồng thời có thể hoặc không thể thực hiện song song.

Yes.

Đó là lý do đằng sau heuristic mà các chủ đề Python chỉ nên được sử dụng cho các nhiệm vụ ràng buộc IO, chứ không phải các nhiệm vụ liên kết CPU, vì các nhiệm vụ ràng buộc IO sẽ chờ trong hạt nhân hệ điều hành để các tài nguyên từ xa phản hồi (không thực hiện các hướng dẫn Python) , cho phép các chủ đề Python khác chạy và thực hiện các hướng dẫn Python.

Như vậy, GIL là một sự cân nhắc khi sử dụng các luồng trong python, chẳng hạn như lớp chủ đề. Nó không phải là một sự cân nhắc khi sử dụng nhóm đa xử lý (trừ khi bạn sử dụng các luồng bổ sung trong mỗi nhiệm vụ).

No.

Bạn có thể tìm hiểu thêm về Pool so với Gil trong hướng dẫn:

Nhóm đa xử lý và khóa phiên dịch toàn cầu (GIL)

Có phải các quá trình Python có phải là các quy trình thực sự không?

Python sử dụng các quy trình cấp hệ thống thực, còn được gọi là quy trình sinh sản hoặc quy trình forking, khả năng được cung cấp bởi các hệ điều hành hiện đại như Windows, Linux và MacOS.

Aren lồng Python Processes Buggy?

Nếu bạn đang sử dụng Python và sau đó bạn cần đồng thời, thì bạn làm việc với những gì bạn có. Câu hỏi là moot.

Nếu bạn cần đồng thời và bạn chưa chọn ngôn ngữ, có lẽ một ngôn ngữ khác sẽ phù hợp hơn, hoặc có lẽ không. Xem xét phạm vi đầy đủ của các yêu cầu chức năng và phi chức năng (hoặc nhu cầu, mong muốn và mong muốn của người dùng) cho dự án của bạn và khả năng của các nền tảng phát triển khác nhau.

Tại sao không sử dụng ThreadPool thay thế?

Đa xử lý.Pool.ThreadPool hỗ trợ các nhóm các luồng, không giống như Multiprocessing.Pool hỗ trợ nhóm các quy trình, trong đó mỗi quy trình sẽ có một luồng.multiprocessing.pool.ThreadPool supports pools of threads, unlike the multiprocessing.Pool that supports pools of processes, where each process will have one thread.

Chủ đề và quy trình khá khác nhau và việc chọn cái này hơn cái kia phải khá cố ý.

Một chương trình Python là một quá trình có chủ đề chính. Bạn có thể tạo nhiều luồng bổ sung trong một quy trình Python. Bạn cũng có thể nĩa hoặc sinh ra nhiều quy trình Python, mỗi quy trình sẽ có một luồng chính và có thể sinh ra các luồng bổ sung.

Nhìn rộng hơn, các luồng nhẹ và có thể chia sẻ bộ nhớ (dữ liệu và biến) trong một quy trình trong khi các quá trình là nặng nề và yêu cầu chi phí cao hơn và áp đặt nhiều giới hạn hơn trong việc chia sẻ bộ nhớ (dữ liệu và biến).

Thông thường trong Python, các quy trình được sử dụng cho các nhiệm vụ và luồng liên kết CPU được sử dụng cho các nhiệm vụ gắn IO, và đây là một heuristic tốt, nhưng điều này không phải là trường hợp.

Có lẽ Multiprocessing.Pool.ThreadPool phù hợp hơn với vấn đề cụ thể của bạn. Có lẽ hãy thử nó và xem.

Tại sao không sử dụng Multiprocessing.Process thay thế?

Đa xử lý.pool giống như chế độ tự động của người dùng cho các quy trình Python.multiprocessing.Pool is like the “automatic mode” for Python processes.

Nếu bạn có một trường hợp sử dụng tinh vi hơn, bạn có thể cần sử dụng lớp đa xử lý trực tiếp.multiprocessing.Process class directly.

Điều này có thể là do bạn yêu cầu đồng bộ hóa nhiều hơn giữa các quy trình với các cơ chế khóa, bộ nhớ được chia sẻ giữa các quy trình như người quản lý và/hoặc phối hợp nhiều hơn giữa các quy trình với các rào cản và semaphores.

Có thể là bạn có một trường hợp sử dụng đơn giản hơn, chẳng hạn như một nhiệm vụ duy nhất, trong trường hợp đó có lẽ một nhóm quy trình sẽ là một giải pháp quá nặng.

Điều đó đang được nói, nếu bạn thấy mình sử dụng lớp quy trình với từ khóa Target Target cho các chức năng thuần túy (các chức năng không có tác dụng phụ), có lẽ bạn sẽ phù hợp hơn với việc sử dụng đa xử lý.pool.Process class with the “target” keyword for pure functions (functions that don’t have side effects), perhaps you would be better suited to using the multiprocessing.Pool.

Bạn có thể tìm hiểu thêm về sự khác biệt giữa nhóm đa xử lý và quy trình trong hướng dẫn:Pool and Process in the tutorial:

  • Đa xử lý hồ bơi so với quy trình trong Python

Tại sao không sử dụng ProcessPoolExecutor thay thế?

Python cung cấp hai nhóm công nhân dựa trên quy trình thông qua lớp đa xử lý.pool.pool và lớp đồng thời.futures.processPoolExecutor.multiprocessing.pool.Pool class and the concurrent.futures.ProcessPoolExecutor class.

Các lớp đa xử lý.Pool và ProcessPoolExecutor rất giống nhau. Cả hai đều là nhóm quy trình của các quy trình lao động trẻ em.multiprocessing.Pool and ProcessPoolExecutor classes are very similar. They are both process pools of child worker processes.

Những điểm tương đồng quan trọng nhất như sau:

  • Cả hai quá trình sử dụng.
  • Cả hai có thể chạy các nhiệm vụ ad hoc.
  • Cả hai hỗ trợ các nhiệm vụ không đồng bộ.
  • Cả hai có thể chờ đợi tất cả các nhiệm vụ.
  • Cả hai đều có tương đương dựa trên chủ đề.

Đa xử lý.Pool và ProcessPoolExecutor cũng khác nhau một cách tinh tế.multiprocessing.Pool and ProcessPoolExecutor are also subtly different.

Chúng tôi khác biệt chính như sau:

Sự khác biệt giữa hai nhóm quy trình này tập trung vào sự khác biệt trong API trên chính các lớp.

  • Đa xử lý.pool không cung cấp khả năng hủy bỏ các tác vụ, trong khi ProcessPoolExecutor.multiprocessing.Pool does not provide the ability to cancel tasks, whereas the ProcessPoolExecutor does.
  • Đa xử lý.pool không cung cấp khả năng làm việc với các bộ sưu tập các nhiệm vụ không đồng nhất, trong khi ProcessPoolExecutor.multiprocessing.Pool does not provide the ability to work with collections of heterogeneous tasks, whereas the ProcessPoolExecutor does.
  • Đa xử lý.pool cung cấp khả năng chấm dứt mạnh mẽ tất cả các tác vụ, trong khi ProcessPoolExecutor thì không.multiprocessing.Pool provides the ability to forcefully terminate all tasks, whereas the ProcessPoolExecutor does not.
  • Đa xử lý.pool cung cấp một trọng tâm vào các phiên bản song song của hàm map (), trong khi processPoolExecutor thì không.multiprocessing.Pool provides a focus on parallel versions of the map() function, whereas the ProcessPoolExecutor does not.
  • Đa xử lý.pool không cung cấp khả năng truy cập một ngoại lệ được nêu ra trong một nhiệm vụ, trong khi ProcessPoolExecutor.multiprocessing.Pool does not provide the ability to access an exception raised in a task, whereas the ProcessPoolExecutor does.

Bạn có thể tìm hiểu thêm về sự khác biệt giữa nhóm đa xử lý và ProcessPoolExecutor trong hướng dẫn:Pool and the ProcessPoolExecutor in the tutorial:

  • Đa bộ xử lý nhóm vs ProcessPoolExecutor trong Python

Tại sao không sử dụng asyncio?

Asyncio có thể là một giải pháp thay thế cho việc sử dụng đa xử lý.Pool.ThreadPool hoặc ThreadPoolExecutor, nhưng có lẽ không phải là một lựa chọn tốt cho đa xử lý.pool.multiprocessing.pool.ThreadPool or ThreadPoolExecutor, but is probably not a good alternative for the multiprocessing.Pool.

Asyncio được thiết kế để hỗ trợ số lượng lớn các hoạt động IO, có lẽ hàng chục ngàn đến hàng chục ngàn, tất cả trong một luồng.

Nó đòi hỏi một mô hình lập trình thay thế, được gọi là lập trình phản ứng, có thể là thách thức cho người mới bắt đầu.

Khi sử dụng đa xử lý.pool, bạn thường thực hiện các tác vụ ràng buộc CPU, không phù hợp khi sử dụng mô-đun Asyncio.multiprocessing.Pool, you are typically executing CPU-bound tasks, which are not appropriate when using the AsyncIO module.

Đọc thêm

Phần này liệt kê các tài nguyên bổ sung hữu ích về chủ đề này.

Sách

  • Bảng gian lận nhóm đa xử lý
  • Câu hỏi phỏng vấn đa xử lý
  • Đa bộ xử lý nhóm khởi động (khóa học 7 ngày của tôi)

Hướng dẫn liên quan

  • ProcessPoolExecutor in Python: Hướng dẫn hoàn chỉnh
  • Đa bộ xử lý trong Python: Hướng dẫn hoàn chỉnh

API

  • Chức năng tích hợp Python
  • Đa xử lý-song song dựa trên quy trình

Người giới thiệu

  • Chủ đề (Điện toán), Wikipedia.
  • Quy trình (Điện toán), Wikipedia.

Kết luận

Đây là một hướng dẫn lớn và bạn đã phát hiện ra rất chi tiết về cách thức đa xử lý.pool hoạt động và cách sử dụng tốt nhất trong dự án của bạn.multiprocessing.Pool works and how to best use it on your project.

Bạn có thấy hướng dẫn này hữu ích không? Tôi rất thích biết.Vui lòng chia sẻ một từ tử tế trong các ý kiến dưới đây.
I’d love to know. Please share a kind word in the comments below.

Bạn đã sử dụng hồ bơi trong một dự án chưa? Tôi rất thích nghe về nó;Xin vui lòng cho tôi biết trong các ý kiến.
I’d love to hear about it; please let me know in the comments.

Bạn có câu hỏi nào không? Để lại câu hỏi của bạn trong một bình luận bên dưới và tôi sẽ trả lời nhanh với lời khuyên tốt nhất của tôi.
Leave your question in a comment below and I will reply fast with my best advice.