Hướng dẫn multithreading vs multiprocessing python speed - tốc độ python đa luồng so với đa xử lý

Trích dẫn tài liệu Python

Phiên bản kinh điển của câu trả lời này hiện đang ở câu hỏi Dupliquee: sự khác biệt giữa các mô -đun phân luồng và đa xử lý là gì?

Tôi đã nhấn mạnh các trích dẫn tài liệu Python chính về quy trình so với các luồng và Gil AT: Khóa phiên dịch toàn cầu (GIL) toàn cầu trong CPython là gì?

Xử lý so với thí nghiệm chủ đề

Tôi đã làm một chút điểm chuẩn để thể hiện sự khác biệt một cách cụ thể hơn.

Trong điểm chuẩn, tôi đã định thời gian CPU và IO bị ràng buộc cho các số lượng chủ đề khác nhau trên CPU 8 hyperthread. Công việc được cung cấp cho mỗi chủ đề luôn giống nhau, như vậy nhiều chủ đề có nghĩa là nhiều công việc được cung cấp hơn.

Kết quả là:

Hướng dẫn multithreading vs multiprocessing python speed - tốc độ python đa luồng so với đa xử lý

Sơ đồ dữ liệu.

Conclusions:

  • Đối với công việc ràng buộc CPU, đa xử lý luôn nhanh hơn, có lẽ là do Gil

  • cho công việc ràng buộc IO. Cả hai đều chính xác là cùng một tốc độ

  • Chủ đề chỉ tỷ lệ lên tới khoảng 4 lần thay vì 8 lần dự kiến ​​vì tôi đang sử dụng 8 máy Hyperthread.

    Tương phản rằng với một công việc gắn CPU CPU POSIX đạt tốc độ 8 lần dự kiến: 'thật', 'người dùng' và 'sys' có ý nghĩa gì trong đầu ra của thời gian (1)?

    TODO: Tôi không biết lý do cho điều này, phải có sự thiếu hiệu quả khác của Python.

Mã kiểm tra:

#!/usr/bin/env python3

import multiprocessing
import threading
import time
import sys

def cpu_func(result, niters):
    '''
    A useless CPU bound function.
    '''
    for i in range(niters):
        result = (result * result * i + 2 * result * i * i + 3) % 10000000
    return result

class CpuThread(threading.Thread):
    def __init__(self, niters):
        super().__init__()
        self.niters = niters
        self.result = 1
    def run(self):
        self.result = cpu_func(self.result, self.niters)

class CpuProcess(multiprocessing.Process):
    def __init__(self, niters):
        super().__init__()
        self.niters = niters
        self.result = 1
    def run(self):
        self.result = cpu_func(self.result, self.niters)

class IoThread(threading.Thread):
    def __init__(self, sleep):
        super().__init__()
        self.sleep = sleep
        self.result = self.sleep
    def run(self):
        time.sleep(self.sleep)

class IoProcess(multiprocessing.Process):
    def __init__(self, sleep):
        super().__init__()
        self.sleep = sleep
        self.result = self.sleep
    def run(self):
        time.sleep(self.sleep)

if __name__ == '__main__':
    cpu_n_iters = int(sys.argv[1])
    sleep = 1
    cpu_count = multiprocessing.cpu_count()
    input_params = [
        (CpuThread, cpu_n_iters),
        (CpuProcess, cpu_n_iters),
        (IoThread, sleep),
        (IoProcess, sleep),
    ]
    header = ['nthreads']
    for thread_class, _ in input_params:
        header.append(thread_class.__name__)
    print(' '.join(header))
    for nthreads in range(1, 2 * cpu_count):
        results = [nthreads]
        for thread_class, work_size in input_params:
            start_time = time.time()
            threads = []
            for i in range(nthreads):
                thread = thread_class(work_size)
                threads.append(thread)
                thread.start()
            for i, thread in enumerate(threads):
                thread.join()
            results.append(time.time() - start_time)
        print(' '.join('{:.6e}'.format(result) for result in results))

GitHub ngược dòng + Mã vẽ âm mưu trên cùng thư mục.

Đã thử nghiệm trên Ubuntu 18.10, Python 3.6.7, trong máy tính xách tay Lenovo ThinkPad p51 với CPU: Intel Core i7-7820HQ CPU (4 lõi / 8 000L7 (3.000 Mb/s).

Trực quan hóa các luồng nào đang chạy tại một thời điểm nhất định

Bài đăng này https://rohanvarma.me/gil/ đã dạy tôi rằng bạn có thể chạy một cuộc gọi lại bất cứ khi nào một luồng được lên lịch với đối số target= của threading.Thread và tương tự cho multiprocessing.Process.

Điều này cho phép chúng tôi xem chính xác chủ đề nào chạy mỗi lần. Khi điều này được thực hiện, chúng ta sẽ thấy một cái gì đó giống như (tôi đã tạo ra biểu đồ cụ thể này):

            +--------------------------------------+
            + Active threads / processes           +
+-----------+--------------------------------------+
|Thread   1 |********     ************             |
|         2 |        *****            *************|
+-----------+--------------------------------------+
|Process  1 |***  ************** ******  ****      |
|         2 |** **** ****** ** ********* **********|
+-----------+--------------------------------------+
            + Time -->                             +
            +--------------------------------------+

Điều đó sẽ cho thấy rằng:

  • Chủ đề được nối tiếp hoàn toàn bởi Gil
  • Các quy trình có thể chạy song song

MultiThreading có nhanh hơn đa xử lý không?

Chủ đề nhanh hơn để bắt đầu so với các quy trình và cũng nhanh hơn trong việc chuyển đổi nhiệm vụ. Tất cả các chủ đề chia sẻ một nhóm bộ nhớ quá trình rất có lợi. Mất ít thời gian hơn để tạo một chủ đề mới trong quy trình hiện có so với một quy trình mới.. All Threads share a process memory pool that is very beneficial. Takes lesser time to create a new thread in the existing process than a new process.

Điều nào là đa xử lý tốt hơn hoặc đa luồng trong Python?

Nếu chương trình của bạn bị ràng buộc, cả đa luồng và đa xử lý trong Python sẽ hoạt động trơn tru. Tuy nhiên, nếu mã bị ràng buộc CPU và máy của bạn có nhiều lõi, đa xử lý sẽ là lựa chọn tốt hơn.If the code is CPU-bound and your machine has multiple cores, multiprocessing would be a better choice.

Là đa bộ xử lý nhanh hơn trong Python?

Vì vậy, đa xử lý nhanh hơn khi chương trình bị ràng buộc CPU.Trong trường hợp có rất nhiều I/O trong chương trình của bạn, việc luồng có thể hiệu quả hơn vì hầu hết thời gian, chương trình của bạn đang chờ hoàn thành I/O.Tuy nhiên, đa xử lý thường hiệu quả hơn vì nó chạy đồng thời.multiprocessing is faster when the program is CPU-bound. In cases where there is a lot of I/O in your program, threading may be more efficient because most of the time, your program is waiting for the I/O to complete. However, multiprocessing is generally more efficient because it runs concurrently.

Có phải luồng python nhanh hơn?

Chủ đề và quy trình mất khoảng thời gian cho nhau, và cả hai đều nhanh hơn sử dụng vòng lặp.Trong chức năng này, không giống như giao thức trước, mỗi tác vụ được hoàn thành bởi các luồng mất cùng một lượng thời gian như khi hoàn thành bởi vòng lặp.. In this function, unlike the previous one, each task completed by threads takes the same amount of time as when completed by the loop.