Hướng dẫn run multi process python - chạy python đa tiến trình

Trong bài này chúng ta sẽ tìm hiểu xử lý đa tiến trình trong Python. Đa xử lý hay còn gọi là multiprocessing, thường được dùng để xử lý nhiều tiến trình chạy song song.multiprocessing, thường được dùng để xử lý nhiều tiến trình chạy song song.

Hướng dẫn run multi process python - chạy python đa tiến trình

Hướng dẫn run multi process python - chạy python đa tiến trình

Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.freetuts.net, không được copy dưới mọi hình thức.

Đa xử lý được tích hợp trong module multiprocessing, trong đó có lớp process, vì vậy bạn phải import thư viện này vào trước khi sử dụng nhé.multiprocessing, trong đó có lớp process, vì vậy bạn phải import thư viện này vào trước khi sử dụng nhé.

1. Multiprocessing là gì?

Multiprocessing là khả năng của một hệ thống hỗ trợ nhiều bộ vi xử lý processor cùng một lúc. Các ưng dụng trong hệ thống đa xử lý được chia thành nhiều quy trình nhỏ và chạy độc lập, và hệ điều hành sẽ phân bổ các luồng này cho bộ vi xử lý để cải thiện hiệu suất của hệ thống.

Câu hỏi đặt ra là tại sao ta phải sư dụng multiprocessing? Hãy đặt một ví dụ về máy tính có một processor nhé.tại sao ta phải sư dụng multiprocessing? Hãy đặt một ví dụ về máy tính có một processor nhé.

Bài viết này được đăng tại [free tuts .net]

Trong máy tính có một processor duy nhất, nếu processor được chỉ định chạy nhiều quy trình cùng lúc thì nó sẽ phải phân chia các task (tác vụ) bằng cách ngắt task này và chạy task kia một cách liên tục, điều này giúp đảm bảo tất cả các task đều được chạy.

Điều này giống như một người đầu bếp, khi khách hàng vào đặt nhiều món thì đầu bếp sẽ phải nấu nhiều món cùng lúc, phân chia thời gian giữa các món để đảm bảo món nào cũng được nấu đúng giờ.

Việc làm nhiều việc cùng lúc sẽ làm cho hiệu quả công việc không được tốt, sản phẩm hoàn thành không được như mong đời. Chính điều này đã xuất hiện thêm khái niệm xử lý đa tiến trình.

2. Multiprocessing trong Python là gì?

Multiprocessing trong Python là một module hỗ trợ lập trình viên có thể phân chia công việc theo nhiều quy trình. Bằng cách thông qua những phương thức (API) mà module cung cấp sẵn, chúng ta có thể quản lý được các task một cách dễ dàng.

Để hiểu rõ về xử lý tiến trình song song thì bạn phải biết có bao nhiêu core trong máy tính đang sử dụng, và module multiprocessing sẽ giúp bạn biết được điều đó, bằng cách sử dụng đoạn mã đơn giản dưới đây.multiprocessing sẽ giúp bạn biết được điều đó, bằng cách sử dụng đoạn mã đơn giản dưới đây.

import multiprocessing
print("Số lượng cpu : ", multiprocessing.cpu_count())

Kết quả trên máy tính của mình là:

Đấy chỉ là mới tham khảo số lượng CPU. Nếu bạn muốn tìm hiểu sâu hơn thì hãy tiếp tục với các ví dụ phía dưới nhé.

Ví dụ 1: Bây giờ hãy xem một đoạn code đơn giản dưới đây.: Bây giờ hãy xem một đoạn code đơn giản dưới đây.

# importing module multiprocessing
import multiprocessing

def print_cube(num):
    """
    Hàm in thể tích của khối lập phương
    """
    print("Giá trị lập phương: {}".format(num * num * num))

def print_square(num):
    """
    Hàm in diện tích hình vuông
    """
    print("Diện tích hình vuông: {}".format(num * num))

# Chương trình chính
if __name__ == "__main__":
    # Tạo hai tiến trình process
    p1 = multiprocessing.Process(target=print_square, args=(10, ))
    p2 = multiprocessing.Process(target=print_cube, args=(10, ))

    # Bắt đầu process 1
    p1.start()
    # Bắt đầu process 2
    p2.start()

    # Chờ tới khi process 1 hoàn thành
    p1.join()
    # Chờ tới khi process 2 hoàn thành
    p2.join()

    # Cả hai processes hoàn thành
    print("Done!")

Kết quả:

Diện tích hình vuông: 100
Giá trị lập phương: 1000
Done!

Giải thích một chút về chương trình:

  • Đoạn code import multiprocessing dùng để khai báo sử dụng module multiprocessing.
  • Để tạo một process thì ta sử dụng class tên là Process, nó có hai tham số như sau: Process, nó có hai tham số như sau:
    • # importing module multiprocessing
      import multiprocessing
      
      def print_cube(num):
          """
          Hàm in thể tích của khối lập phương
          """
          print("Giá trị lập phương: {}".format(num * num * num))
      
      def print_square(num):
          """
          Hàm in diện tích hình vuông
          """
          print("Diện tích hình vuông: {}".format(num * num))
      
      # Chương trình chính
      if __name__ == "__main__":
          # Tạo hai tiến trình process
          p1 = multiprocessing.Process(target=print_square, args=(10, ))
          p2 = multiprocessing.Process(target=print_cube, args=(10, ))
      
          # Bắt đầu process 1
          p1.start()
          # Bắt đầu process 2
          p2.start()
      
          # Chờ tới khi process 1 hoàn thành
          p1.join()
          # Chờ tới khi process 2 hoàn thành
          p2.join()
      
          # Cả hai processes hoàn thành
          print("Done!")
      0 là hàm được gọi để chạy
    • # importing module multiprocessing
      import multiprocessing
      
      def print_cube(num):
          """
          Hàm in thể tích của khối lập phương
          """
          print("Giá trị lập phương: {}".format(num * num * num))
      
      def print_square(num):
          """
          Hàm in diện tích hình vuông
          """
          print("Diện tích hình vuông: {}".format(num * num))
      
      # Chương trình chính
      if __name__ == "__main__":
          # Tạo hai tiến trình process
          p1 = multiprocessing.Process(target=print_square, args=(10, ))
          p2 = multiprocessing.Process(target=print_cube, args=(10, ))
      
          # Bắt đầu process 1
          p1.start()
          # Bắt đầu process 2
          p2.start()
      
          # Chờ tới khi process 1 hoàn thành
          p1.join()
          # Chờ tới khi process 2 hoàn thành
          p2.join()
      
          # Cả hai processes hoàn thành
          print("Done!")
      1 là các tham số sẽ truyền vào hàm target
    • Class
      # importing module multiprocessing
      import multiprocessing
      
      def print_cube(num):
          """
          Hàm in thể tích của khối lập phương
          """
          print("Giá trị lập phương: {}".format(num * num * num))
      
      def print_square(num):
          """
          Hàm in diện tích hình vuông
          """
          print("Diện tích hình vuông: {}".format(num * num))
      
      # Chương trình chính
      if __name__ == "__main__":
          # Tạo hai tiến trình process
          p1 = multiprocessing.Process(target=print_square, args=(10, ))
          p2 = multiprocessing.Process(target=print_cube, args=(10, ))
      
          # Bắt đầu process 1
          p1.start()
          # Bắt đầu process 2
          p2.start()
      
          # Chờ tới khi process 1 hoàn thành
          p1.join()
          # Chờ tới khi process 2 hoàn thành
          p2.join()
      
          # Cả hai processes hoàn thành
          print("Done!")
      2 cũng có thêm các tham số khác, nhưng chúng ta sẽ tìm hiểu nó sau nhé.
  • Để bắt đầu một tiến trình thì ta gọi đến phương thức start.start.
  • Để dừng chương trình tạm thời, tức là chờ hai tiến trình xử lý xong thì ta sử dụng phương thức join.join.
  • Như vậy đoạn code
    # importing module multiprocessing
    import multiprocessing
    
    def print_cube(num):
        """
        Hàm in thể tích của khối lập phương
        """
        print("Giá trị lập phương: {}".format(num * num * num))
    
    def print_square(num):
        """
        Hàm in diện tích hình vuông
        """
        print("Diện tích hình vuông: {}".format(num * num))
    
    # Chương trình chính
    if __name__ == "__main__":
        # Tạo hai tiến trình process
        p1 = multiprocessing.Process(target=print_square, args=(10, ))
        p2 = multiprocessing.Process(target=print_cube, args=(10, ))
    
        # Bắt đầu process 1
        p1.start()
        # Bắt đầu process 2
        p2.start()
    
        # Chờ tới khi process 1 hoàn thành
        p1.join()
        # Chờ tới khi process 2 hoàn thành
        p2.join()
    
        # Cả hai processes hoàn thành
        print("Done!")
    3 chỉ được thực chạy khi hai tiến trình phía trên hoàn thành.

Nếu bạn vẫn chưa hình dung được việc xử lý các tiến trình là riêng biệt thì hãy tham khảo thêm ví dụ 2 dưới đây.

Ví dụ 2: Kiểm tra process ID và trạng thái của process.: Kiểm tra process ID và trạng thái của process.

# importing multiprocessing và os module
import multiprocessing
import os

def worker1():
    # In ra process id của worker1
    print("ID của tiến trình worker1: {}".format(os.getpid()))

def worker2():
    # In ra process id của worker2
    print("ID của tiến trình worker2: {}".format(os.getpid()))

# Chương trình chính
if __name__ == "__main__":
    # In ra process id của chương trình chính
    print("ID của chương trình chính: {}".format(os.getpid()))

    # Tạo processes
    p1 = multiprocessing.Process(target=worker1)
    p2 = multiprocessing.Process(target=worker2)

    # Chạy processes
    p1.start()
    p2.start()

    # Lấy process IDs
    print("ID của process p1: {}".format(p1.pid))
    print("ID của process p2: {}".format(p2.pid))

    # Chờ cho tới khi 2 process p1 và p2 hoàn thành
    p1.join()
    p2.join()

    # In thông báo cả hai đã hoàn thành
    print("Cả hai tiến trình đã hoàn thành!")

    # Kiểm tra trạng thái của hai process
    print("Process p1 có đang chạy? {}".format(p1.is_alive()))
    print("Process p2 có đang chạy? {}".format(p2.is_alive()))

Kết quả::

ID của chương trình chính: 2928
ID của process p1: 6160
ID của process p2: 9208
ID của tiến trình worker1: 6160
ID của tiến trình worker2: 9208
Cả hai tiến trình đã hoàn thành!
Process p1 có đang chạy? False
Process p2 có đang chạy? False

Giải thích một chút về chương trình:

  • Đoạn code import multiprocessing dùng để khai báo sử dụng module multiprocessing.is_alive() dùng để kiểm tra một tiến trình đang live hay không.
  • Để tạo một process thì ta sử dụng class tên là Process, nó có hai tham số như sau: pid lưu trữ ID của tiến trình.
  • # importing module multiprocessing
    import multiprocessing
    
    def print_cube(num):
        """
        Hàm in thể tích của khối lập phương
        """
        print("Giá trị lập phương: {}".format(num * num * num))
    
    def print_square(num):
        """
        Hàm in diện tích hình vuông
        """
        print("Diện tích hình vuông: {}".format(num * num))
    
    # Chương trình chính
    if __name__ == "__main__":
        # Tạo hai tiến trình process
        p1 = multiprocessing.Process(target=print_square, args=(10, ))
        p2 = multiprocessing.Process(target=print_cube, args=(10, ))
    
        # Bắt đầu process 1
        p1.start()
        # Bắt đầu process 2
        p2.start()
    
        # Chờ tới khi process 1 hoàn thành
        p1.join()
        # Chờ tới khi process 2 hoàn thành
        p2.join()
    
        # Cả hai processes hoàn thành
        print("Done!")
    0 là hàm được gọi để chạy

# importing module multiprocessing
import multiprocessing

def print_cube(num):
    """
    Hàm in thể tích của khối lập phương
    """
    print("Giá trị lập phương: {}".format(num * num * num))

def print_square(num):
    """
    Hàm in diện tích hình vuông
    """
    print("Diện tích hình vuông: {}".format(num * num))

# Chương trình chính
if __name__ == "__main__":
    # Tạo hai tiến trình process
    p1 = multiprocessing.Process(target=print_square, args=(10, ))
    p2 = multiprocessing.Process(target=print_cube, args=(10, ))

    # Bắt đầu process 1
    p1.start()
    # Bắt đầu process 2
    p2.start()

    # Chờ tới khi process 1 hoàn thành
    p1.join()
    # Chờ tới khi process 2 hoàn thành
    p2.join()

    # Cả hai processes hoàn thành
    print("Done!")
1 là các tham số sẽ truyền vào hàm target

Hướng dẫn run multi process python - chạy python đa tiến trình

Class

# importing module multiprocessing
import multiprocessing

def print_cube(num):
    """
    Hàm in thể tích của khối lập phương
    """
    print("Giá trị lập phương: {}".format(num * num * num))

def print_square(num):
    """
    Hàm in diện tích hình vuông
    """
    print("Diện tích hình vuông: {}".format(num * num))

# Chương trình chính
if __name__ == "__main__":
    # Tạo hai tiến trình process
    p1 = multiprocessing.Process(target=print_square, args=(10, ))
    p2 = multiprocessing.Process(target=print_cube, args=(10, ))

    # Bắt đầu process 1
    p1.start()
    # Bắt đầu process 2
    p2.start()

    # Chờ tới khi process 1 hoàn thành
    p1.join()
    # Chờ tới khi process 2 hoàn thành
    p2.join()

    # Cả hai processes hoàn thành
    print("Done!")
2 cũng có thêm các tham số khác, nhưng chúng ta sẽ tìm hiểu nó sau nhé.

Để bắt đầu một tiến trình thì ta gọi đến phương thức start.

Để dừng chương trình tạm thời, tức là chờ hai tiến trình xử lý xong thì ta sử dụng phương thức join.chạy độc lập và có không gian bộ nhớ riêng.

Như vậy đoạn code

# importing module multiprocessing
import multiprocessing

def print_cube(num):
    """
    Hàm in thể tích của khối lập phương
    """
    print("Giá trị lập phương: {}".format(num * num * num))

def print_square(num):
    """
    Hàm in diện tích hình vuông
    """
    print("Diện tích hình vuông: {}".format(num * num))

# Chương trình chính
if __name__ == "__main__":
    # Tạo hai tiến trình process
    p1 = multiprocessing.Process(target=print_square, args=(10, ))
    p2 = multiprocessing.Process(target=print_cube, args=(10, ))

    # Bắt đầu process 1
    p1.start()
    # Bắt đầu process 2
    p2.start()

    # Chờ tới khi process 1 hoàn thành
    p1.join()
    # Chờ tới khi process 2 hoàn thành
    p2.join()

    # Cả hai processes hoàn thành
    print("Done!")
3 chỉ được thực chạy khi hai tiến trình phía trên hoàn thành.global ở hai tiến trình khác nhau thì việc thay giá trị cho biến đó ở hai tiến trình là không ảnh hưởng đến nhau.

Nếu bạn vẫn chưa hình dung được việc xử lý các tiến trình là riêng biệt thì hãy tham khảo thêm ví dụ 2 dưới đây.

import multiprocessing

# Biến global là một mảng rỗng
result = []

def process1():
    """ Hàm chạy tiến trình 1"""
    global result
    result.append(100)
    print("Result trong process1:", result)


if __name__ == "__main__":

    # Tạo process1
    p1 = multiprocessing.Process(target=process1, args=())

    # Bắt đầu
    p1.start()

    # Chờ cho tới khi p1 hoàn thành
    p1.join()

    # Kiểm tra xem result có thay đổi không
    print("Result trong main: ".format(result))

Kết quả:

Result trong process1: [100]
Result trong main: 

Giải thích một chút về chương trình:

  • Đoạn code import multiprocessing dùng để khai báo sử dụng module multiprocessing.
  • Để tạo một process thì ta sử dụng class tên là Process, nó có hai tham số như sau:
  • # importing module multiprocessing
    import multiprocessing
    
    def print_cube(num):
        """
        Hàm in thể tích của khối lập phương
        """
        print("Giá trị lập phương: {}".format(num * num * num))
    
    def print_square(num):
        """
        Hàm in diện tích hình vuông
        """
        print("Diện tích hình vuông: {}".format(num * num))
    
    # Chương trình chính
    if __name__ == "__main__":
        # Tạo hai tiến trình process
        p1 = multiprocessing.Process(target=print_square, args=(10, ))
        p2 = multiprocessing.Process(target=print_cube, args=(10, ))
    
        # Bắt đầu process 1
        p1.start()
        # Bắt đầu process 2
        p2.start()
    
        # Chờ tới khi process 1 hoàn thành
        p1.join()
        # Chờ tới khi process 2 hoàn thành
        p2.join()
    
        # Cả hai processes hoàn thành
        print("Done!")
    0 là hàm được gọi để chạy
  • # importing module multiprocessing
    import multiprocessing
    
    def print_cube(num):
        """
        Hàm in thể tích của khối lập phương
        """
        print("Giá trị lập phương: {}".format(num * num * num))
    
    def print_square(num):
        """
        Hàm in diện tích hình vuông
        """
        print("Diện tích hình vuông: {}".format(num * num))
    
    # Chương trình chính
    if __name__ == "__main__":
        # Tạo hai tiến trình process
        p1 = multiprocessing.Process(target=print_square, args=(10, ))
        p2 = multiprocessing.Process(target=print_cube, args=(10, ))
    
        # Bắt đầu process 1
        p1.start()
        # Bắt đầu process 2
        p2.start()
    
        # Chờ tới khi process 1 hoàn thành
        p1.join()
        # Chờ tới khi process 2 hoàn thành
        p2.join()
    
        # Cả hai processes hoàn thành
        print("Done!")
    1 là các tham số sẽ truyền vào hàm target

Class

# importing module multiprocessing
import multiprocessing

def print_cube(num):
    """
    Hàm in thể tích của khối lập phương
    """
    print("Giá trị lập phương: {}".format(num * num * num))

def print_square(num):
    """
    Hàm in diện tích hình vuông
    """
    print("Diện tích hình vuông: {}".format(num * num))

# Chương trình chính
if __name__ == "__main__":
    # Tạo hai tiến trình process
    p1 = multiprocessing.Process(target=print_square, args=(10, ))
    p2 = multiprocessing.Process(target=print_cube, args=(10, ))

    # Bắt đầu process 1
    p1.start()
    # Bắt đầu process 2
    p2.start()

    # Chờ tới khi process 1 hoàn thành
    p1.join()
    # Chờ tới khi process 2 hoàn thành
    p2.join()

    # Cả hai processes hoàn thành
    print("Done!")
2 cũng có thêm các tham số khác, nhưng chúng ta sẽ tìm hiểu nó sau nhé.

Để bắt đầu một tiến trình thì ta gọi đến phương thức start.

Để dừng chương trình tạm thời, tức là chờ hai tiến trình xử lý xong thì ta sử dụng phương thức join.share dữ liệu giữa chúng thì làm thế nào?

Như vậy đoạn code

# importing module multiprocessing
import multiprocessing

def print_cube(num):
    """
    Hàm in thể tích của khối lập phương
    """
    print("Giá trị lập phương: {}".format(num * num * num))

def print_square(num):
    """
    Hàm in diện tích hình vuông
    """
    print("Diện tích hình vuông: {}".format(num * num))

# Chương trình chính
if __name__ == "__main__":
    # Tạo hai tiến trình process
    p1 = multiprocessing.Process(target=print_square, args=(10, ))
    p2 = multiprocessing.Process(target=print_cube, args=(10, ))

    # Bắt đầu process 1
    p1.start()
    # Bắt đầu process 2
    p2.start()

    # Chờ tới khi process 1 hoàn thành
    p1.join()
    # Chờ tới khi process 2 hoàn thành
    p2.join()

    # Cả hai processes hoàn thành
    print("Done!")
3 chỉ được thực chạy khi hai tiến trình phía trên hoàn thành.

  • Nếu bạn vẫn chưa hình dung được việc xử lý các tiến trình là riêng biệt thì hãy tham khảo thêm ví dụ 2 dưới đây.
  • Ví dụ 2: Kiểm tra process ID và trạng thái của process.

import multiprocessing

def process1(arrayObj, valueObj):
    valueObj.value = 1000
    arrayObj[0] = 10
    arrayObj[1] = 20
    arrayObj[2] = 30
    arrayObj[3] = 40

    print("______________________________")
    print("Giá trị BÊN TRONG tiến trình")
    print('Array: ', arrayObj[:])
    print('Value: ', valueObj.value)


if __name__ == "__main__":
    # Tạo một mảng kiểu int gồm 4 phần tử
    arrayObj = multiprocessing.Array('i', 4)

    # Tạo một giá trị kiểu int
    valueObj = multiprocessing.Value('i')

    print("Giá trị TRƯỚC khi gọi tiến trình")
    print('Array: ', arrayObj[:])
    print('Value: ', valueObj.value)

    # Tạo và chạy tiến trình
    p1 = multiprocessing.Process(target=process1, args=(arrayObj, valueObj))
    p1.start()
    p1.join()

    print("______________________________")
    print("Giá trị SAU khi gọi tiến trình")
    print('Array: ', arrayObj[:])
    print('Value: ', valueObj.value)

Kết quả:

Giá trị TRƯỚC khi gọi tiến trình
Array:  [0, 0, 0, 0]
Value:  0
______________________________
Giá trị BÊN TRONG tiến trình
Array:  [10, 20, 30, 40]
Value:  1000
______________________________
Giá trị SAU khi gọi tiến trình
Array:  [10, 20, 30, 40]
Value:  1000

Bên trong tiến trình process1 mình đã thay đổi giá trị cho các đối tượng Array và Value, và nó được lưu lại cho mọi tiến trình chạy sau nó.process1 mình đã thay đổi giá trị cho các đối tượng Array và Value, và nó được lưu lại cho mọi tiến trình chạy sau nó.

Lời kết: Trên là tổng hợp một số kiến thức quan trọng về xử lý đa tiến trình multiprocessing trong Python. Đây là một kiến thức nâng cao khá hay, và mình nghĩ các bạn nên dành chút thời gian để thực hành theo sẽ giúp ích rất nhiều trong việc hiểu về đa tiến trình.: Trên là tổng hợp một số kiến thức quan trọng về xử lý đa tiến trình multiprocessing trong Python. Đây là một kiến thức nâng cao khá hay, và mình nghĩ các bạn nên dành chút thời gian để thực hành theo sẽ giúp ích rất nhiều trong việc hiểu về đa tiến trình.