Почему одновременное использование нескольких PRNGS приводит к предвзятым результатам?

#python #random

#python #Случайный

Вопрос:

 import random as r
from random import Random
from threading import Thread
#ap = amount of random points
#load_split = how many threads are tasked with it
def pi(ap=1000000,load_split=16):
#circle hits
    c,=0,
#chooses a random point and sees if it is in the circle
    def t(seed,ap=ap/load_split):
        nonlocal c
        r = Random()
        r.seed(seed)
        while ap>0:
            if ((r.random()-0.5)**2 (r.random()-0.5)**2)**0.5<=0.5: c =1
            ap-=1
    th = []
    for i in range(load_split):
        thr = Thread(target=t,args=[r.random()*i])
        thr.start()
        th.append(thr)
#executes the random tries lost to the threads
    for i in range(ap%load_split): 
        if ((r.random()-0.5)**2 (r.random()-0.5)**2)**0.5<=0.5: c =1
#waiting for threads to complete
    for i in th: i.join()
    return 4 * c / ap
input(pi())
  

Почему приблизительные значения pi уменьшаются, когда я распределяю нагрузку по большему количеству потоков?

Сначала я подумал, что это может быть из-за использования одного и того же начального числа, поэтому я генерирую разные локальные Random значения для каждого Thread , каждое из которых рандомизируется, а не просто увеличивает целочисленные значения. (Хотя я не думаю, что последняя часть изменила ситуацию)

Но проблема все еще сохраняется. Кто-нибудь знает причину такого поведения?

Комментарии:

1. Почему вы вызываете input(pi()) ?

2. Что вы подразумеваете под «приблизительными значениями pi, которые становятся меньше»? Вы имеете в виду, что они приближаются к правильному значению?

3. Возможно, это из-за ap=ap/load_split . Так ap меньше с большим количеством потоков.

4. Вероятно, вам нужен мьютекс вокруг приращений c .

5. я запускаю его из проводника, поэтому функция ввода () предотвращает закрытие окна.

Ответ №1:

 import random as r
from random import Random
from threading import Thread
def pi(ap=8000000,load_split=4):
    c=[]
    for i in range(load_split): c.append(0)
#now each thread writes to its own circle hit count
    def t(seed,ap=ap/load_split):
        r = Random()
        r.seed(seed)
        while ap>0:
            if ((r.random()-0.5)**2 (r.random()-0.5)**2)**0.5<=0.5:
                c[seed] =1
            ap-=1
    th = []
    for i in range(load_split):
        thr = Thread(target=t,args=[i])
        thr.start()
        th.append(thr)
    for i in range(ap%load_split): 
        if ((r.random()-0.5)**2 (r.random()-0.5)**2)**0.5<=0.5: c =1
    for i in th: i.join()
    return 4 * sum(c) / ap
input(pi())