簡體   English   中英

random.random() 在多處理中生成相同的數字

[英]random.random() generates same number in multiprocessing

我正在研究一個優化問題,您可以在下面看到我的代碼的簡化版本(原始代碼太復雜,無法提出這樣的問題,我希望我的簡化代碼盡可能地模擬了原始代碼) .

我的目的:在函數optimization中使用函數foo ,但是由於一些困難的情況, foo可能需要很長時間。 所以我使用multiprocessing來設置函數執行的時間限制( proc.join(iter_time) ,該方法來自這個問題的答案; 如何限制函數調用的執行時間? )。

我的問題

  1. while循環中,每次extra生成的值都是一樣的。
  2. 列表lst的長度始終為 1,這意味着在while循環中的每次迭代中,它都從一個空列表開始。

我的猜測:可能的原因可能是每次創建process時隨機種子從頭開始計數,每次process終止時,可能有一些垃圾收集機制來清理process使用的內存,因此列表被清除.

我的問題

  1. 有誰知道這些問題的真正原因?
  2. 如果不使用multiprocessing ,還有其他方法可以在生成不同隨機數的同時實現我的目的嗎? 順便說一句,我嘗試過func_timeout但它還有其他我無法處理的問題......
random.seed(123)
lst = []  # a global list for logging data

def foo(epoch):
    ...
    extra = random.random()
    lst.append(epoch + extra)
    ...

def optimization(loop_time, iter_time):
    start = time.time()
    epoch = 0
    while time.time() <= start + loop_time:
        proc = multiprocessing.Process(target=foo, args=(epoch,))
        proc.start()
        proc.join(iter_time)
        if proc.is_alive():  # if the process is not terminated within time limit
            print("Time out!")
            proc.terminate()

if __name__ == '__main__':
    optimization(300, 2)

如果要跨進程共享變量,則需要使用共享內存。 這是因為子進程不與父進程共享它們的內存空間。 在這里執行此操作的最簡單方法是使用托管列表刪除您設置數字種子的行 這就是導致生成相同數字的原因,因為所有子進程都將采用相同的種子來生成隨機數。 要獲得不同的隨機數,要么不設置種子,要么將不同的種子傳遞給每個進程:

import time, random
from multiprocessing import Manager, Process

def foo(epoch, lst):
    extra = random.random()
    lst.append(epoch + extra)

def optimization(loop_time, iter_time, lst):
    start = time.time()
    epoch = 0
    while time.time() <= start + loop_time:
        proc = Process(target=foo, args=(epoch, lst))
        proc.start()
        proc.join(iter_time)
        if proc.is_alive():  # if the process is not terminated within time limit
            print("Time out!")
            proc.terminate()
    print(lst)

if __name__ == '__main__':
    manager = Manager()
    lst = manager.list()
    optimization(10, 2, lst)

輸出

[0.2035898948744943, 0.07617925389396074, 0.6416754412198231, 0.6712193790613651, 0.419777147554235, 0.732982735576982, 0.7137712131028766, 0.22875414425414997, 0.3181113880578589, 0.5613367673646847, 0.8699685474084119, 0.9005359611195111, 0.23695341111251134, 0.05994288664062197, 0.2306562314450149, 0.15575356275408125, 0.07435292814989103, 0.8542361251850187, 0.13139055891993145, 0.5015152768477814, 0.19864873743952582, 0.2313646288041601, 0.28992667535697736, 0.6265055915510219, 0.7265797043535446, 0.9202923318284002, 0.6321511834038631, 0.6728367262605407, 0.6586979597202935, 0.1309226720786667, 0.563889613032526, 0.389358766191921, 0.37260564565714316, 0.24684684162272597, 0.5982042933298861, 0.896663326233504, 0.7884030244369596, 0.6202229004466849, 0.4417549843477827, 0.37304274232635715, 0.5442716244427301, 0.9915536257041505, 0.46278512685707873, 0.4868394190894778, 0.2133187095154937]

請記住,使用管理器會影響代碼的性能。 除此之外,您還可以使用multiprocessing.Array ,它比管理器更快,但它可以存儲的數據不太靈活,或者隊列也是如此。

暫無
暫無

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

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