【问题标题】:How can I make this multithreaded?我怎样才能使这个多线程?
【发布时间】:2022-01-17 13:30:36
【问题描述】:

我做了一个 Python 脚本来模拟一个骰子,然后计算相对频率。

我想,为什么不让它多线程呢?现在我被变量困住了。如果我运行它,就像最后一个线程会覆盖所有其他结果,所以它将运行多线程但只获取最后一个线程的结果。根据您的需要修改变量尝试,它设置为 8,因此您看到只有 2 个随机数被采用并在最后计算为百分比。不要修改 NrThreads,因为它总是从 4 开始。

import threading
import random


### CONFIGURE
tries=8
NrThreads=4
triesThread=round(round(tries)/4)
###\CONFIGURE

def ThreadCode():
    global one
    global two
    global three
    global four
    global five
    global six
    one=0
    two=0
    three=0
    four=0
    five=0
    six=0
    for i in range(0, triesThread):
        number=random.randint(1,6)
        if (number == 1):
            one=one+1
        if (number == 2):
            two=two+1
        if (number == 3):
            three=three+1
        if (number == 4):
            four=four+1
        if (number == 5):
            five=five+1
        if (number == 6):
            six=six+1

thread1 = threading.Thread(target=ThreadCode)
thread1.start()
print("Started thread")
thread2 = threading.Thread(target=ThreadCode)
thread2.start()
print("Started thread")
thread3 = threading.Thread(target=ThreadCode)
thread3.start()
print("Started thread")
thread4 = threading.Thread(target=ThreadCode)
thread4.start()
print("Started thread")
thread1.join()
thread2.join()
thread3.join()
thread4.join()

print("Number 1: ", one)
print("Number 2: ", two)
print("Number 3: ", three)
print("Number 4: ", four)
print("Number 5: ", five)
print("Number 6: ", six)

p1=one/tries
print("Probability for number 1: ", p1)

for i in ([one, two, three, four, five, six]):
    print(i/tries,"  ", i/tries*100,"%")

【问题讨论】:

  • 如果您这样做是为了了解 python 中的并行性,@bharel 的答案很好,如果您想了解统计/随机性,那么我建议您查看Multinomial distribution (e.g. in numpy),这将以更少的代码更高效地完成此任务

标签: python-3.x random global-variables python-multithreading


【解决方案1】:

您的代码有一些问题:

  1. 您在每个线程中将数字重置为 0。每次函数进入时,它们都会返回 0。
  2. 您的代码不是线程安全的。不能在同一个号码的多个线程中使用+=,否则会互相覆盖。

请记住,这段代码实际上并不会更快,因为 Python 有一个全局解释器锁 (GIL),而且无论如何您都需要锁定所有添加项。

这是固定代码:

import threading
import random


### CONFIGURE
tries=8
NrThreads=4
triesThread=round(tries/4)
###\CONFIGURE

lock = threading.Lock()
one=0
two=0
three=0
four=0
five=0
six=0

def ThreadCode():
    global one
    global two
    global three
    global four
    global five
    global six
    for i in range(0, triesThread):
        number=random.randint(1,6)
        with lock:
            match number:
                case 1:
                    one += 1
                case 2:
                    two += 1
                case 3:
                    three += 1
                case 4:
                    four += 1
                case 5:
                    five += 1
                case 6:
                    six += 1

thread1 = threading.Thread(target=ThreadCode)
thread1.start()
print("Started thread")
thread2 = threading.Thread(target=ThreadCode)
thread2.start()
print("Started thread")
thread3 = threading.Thread(target=ThreadCode)
thread3.start()
print("Started thread")
thread4 = threading.Thread(target=ThreadCode)
thread4.start()
print("Started thread")
thread1.join()
thread2.join()
thread3.join()
thread4.join()

print("Number 1: ", one)
print("Number 2: ", two)
print("Number 3: ", three)
print("Number 4: ", four)
print("Number 5: ", five)
print("Number 6: ", six)

p1=one/tries
print("Probability for number 1: ", p1)

for i in ([one, two, three, four, five, six]):
    print(i/tries,"  ", i/tries*100,"%")

【讨论】:

  • Keep in mind this code won't actually be faster because ...。我可以解决这个问题吗?
  • Number 1: 0 Number 2: 2 Number 3: 2 Number 4: 3 Number 5: 4 Number 6: 1 似乎仍然没有修复。它现在做得太多了。尝试是 8,结果高于 8:4 多于 8。10 只多 2。为什么是这样?因为 TriesThread 的四舍五入?但 8/4 不需要四舍五入。
  • @france1 不幸的是你不能让它更快。添加变量需要有一个锁。修正了计数。
  • 可能会快一点,现在需要一个 cpu 核心的 120-150%
  • 如果你想让它更快,你可以产生不同的进程。此操作的开销非常高,并且在任何少于几百万的数字中实际上不会更快,但它会将操作分散到所有内核。
猜你喜欢
  • 2021-07-14
  • 2012-04-15
  • 2020-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-13
  • 1970-01-01
  • 2020-08-14
相关资源
最近更新 更多