首页 > 解决方案 > 多线程和单线程在 Python 中提供相同的性能

问题描述

在下面的代码中,如果我注释“第 6 行”并取消注释“第 3、4、5 行”。代码在主线程中运行,耗时 17 秒。

现在,如果我取消注释“第 6 行”并注释“第 3、4、5 行”。取消注释“第 1 行”并注释“第 2 行”,然后代码在多线程(创建 3 个线程)中运行,所用时间再次为 17 秒。所以多线程和单线程需要相同的时间。

现在,如果我取消注释“第 6 行”并注释“第 3、4、5 行”。并注释“第 1 行”并取消注释“第 2 行”,然后代码在多进程中运行(创建 3 个进程)所用时间为 9 秒。与单步和多步相比,多处理的工作速度更快。

请让我们知道为什么多线程性能与单线程相同?

import threading
import time
import multiprocessing
import multiprocessing.pool

class xyz:
    def __init__(self):
        self.data = []
        pass
    def loopData(self):
        item = range(0, 100000000)
        for i in item:
            self.data.append(i)

    def loopDatamulti(self):
        num_of_thread = 3
        thread_list = []
        while True:
            t = threading.Thread(target=self.loopData, args=()) #line 1
            #t = multiprocessing.Process(target=self.loopData,args=()) #line 2
            thread_list.append(t)
            
            num_of_thread_created = len(thread_list)
            if num_of_thread_created == num_of_thread:
                break

        for t in thread_list:
            t.start()

        for t in thread_list:
            t.join()

def main():
    print("Start")
    start_time = time.time()

    xa = xyz()
    #xa.loopData() #line 3
    #xa.loopData() #line 4
    #xa.loopData() #line 5
    xa.loopDatamulti() #line 6
    end_time = time.time()
    strLog = "total time {}".format(end_time - start_time)
    print(strLog)

if __name__ == "__main__":
    main()

标签: pythonmultithreadingmultiprocessing

解决方案


多线程不太适合执行纯 CPU 密集型的函数。如果这些函数永远不会产生 CPU(例如,对于某种 I/O),它们只会“锁定”单个 CPU,您将不会获得任何好处。这就是多处理发挥作用的地方。即使这样,您也需要小心,因为如果您的函数是短暂的,那么创建单独进程的开销可能会超过您可能期望的优势。这是一个多处理的例子。使用变量 ITERS 和 PROCS 看看行为如何变化,你就会明白这一点。函数 (myFunc) 只是执行任意伪随机计算并构建一个列表以返回。

from datetime import datetime
from multiprocessing import Pool
import math
import random

ITERS = 100_000
PROCS = 100


def myFunc(r):
    return [(math.sqrt(random.randint(1, 2000))**2)**(1 / 3) for _ in range(r)]


if __name__ == '__main__':
    _start = datetime.now()

    with Pool() as pool:
        for p in [pool.apply_async(func=myFunc, args=(ITERS,))
                  for _ in range(PROCS)]:
            p.wait()

    _end = datetime.now()

    print(f'Multi-processing duration={_end-_start}')

    _start = datetime.now()

    for I in range(PROCS):
        myFunc(ITERS)

    _end = datetime.now()

    print(f'Single-threaded duration={_end-_start}')

在我的机器上,使用代码中显示的 ITERS 和 PROCS 的值,输出如下:-

多处理时长=0:00:01.526478
单线程时长=0:00:09.776963


推荐阅读