簡體   English   中英

如何使用多線程使這個 Python 程序更快?

[英]How to make this Python program faster using multithreading?

我做了一個簡單的程序來執行一些數學運算,我想使用多線程讓它更快。 我知道 Python 的 GIL 會阻止真正的多線程處理,但仍然存在可以改善執行時間的情況。

在這種情況下,程序的線程和非線程執行時間似乎相似,因此似乎沒有任何性能改進。 我知道多處理模塊,但由於它在執行共享 memory 操作時的限制,我想避免這種情況。 有什么方法可以使用多線程在這個程序中顯着提高速度?

謝謝

import string, random, threading

def getLetters():
  letterList = []
  for letter in string.ascii_lowercase:
    letterList.append(letter)
  return letterList

def getNum(letter):
  letterVal = ord(letter)
  rand = random.randint(1,5000000)
  result = 0

  for num in range(0,rand):
    if num%2 == 0:
      result+=num
    else:
      result-=num

  result*=letterVal
  print(f"Result: {result}")
  return result

def mainWithThreading():
  letters = getLetters()
  threadList = []
  for letter in letters:
    th = threading.Thread(target=getNum, args=[letter], daemon=True)
    threadList.append(th)
  for th in threadList:
    th.start()
  for th in threadList:
    th.join()

def mainWithoutThreading():
  letters = getLetters()
  for letter in letters:
    getNum(letter)

start = time.time()
mainWithoutThreading()
end = time.time()
print(f"Time taken: {end-start:.2f}s\n")

start = time.time()
mainWithThreading()
end = time.time()
print(f"Time taken: {end-start:.2f}s\n")

一些代碼發生了變化——主要是為了利用多處理,但也刪除了一些冗余。

from concurrent.futures import ProcessPoolExecutor
from string import ascii_letters
from random import randint
from time import perf_counter

def getNum(c):
    letterVal = ord(c)
    result = 0
    for num in range(randint(1, 5_000_000)):
        # the calculations within this loop serve no purpose other
        # than to make Python do "work"
        if num % 2 == 0:
            result += num
        else:
            result -= num
    result *= letterVal
    return result

def main():
    start = perf_counter()
    with ProcessPoolExecutor() as executor:
        executor.map(getNum, ascii_letters)
    end = perf_counter()
    print(f'Duration after subprocess mapping = {end-start:.2f}s')
    start = perf_counter()
    for c in ascii_letters:
        getNum(c)
    end = perf_counter()
    print(f'Duration after linear processing = {end-start:.2f}s')

if __name__ == '__main__':
    main()

Output:

Duration after subprocess mapping = 1.35s
Duration after linear processing = 8.68s

筆記:

由於getNum() function 中的隨機化,您需要運行幾次才能更清楚地了解多處理如何為這類事情帶來好處。 更好的測試是去掉隨機因素。

通過將getNum()中的循環更改為 200 萬的恆定范圍,結果是:

Duration after subprocess mapping = 1.08s
Duration after linear processing = 7.69s

...這是一個更現實的測試

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM