我想在python中写入一个可以在给定时间段内运行某种算法的类,然后停止并返回其发现的最上调的值直到超时。
。作为一个例子,我写了一个简单的课程,以查找向量中的最大值:
import time, multiprocessing
class AnytimeAlgorithm:
def __init__(self, vector):
self.vector = vector
self.result = 0
def update_forever(self):
while True:
i = random.randint(0, len(self.vector) - 1)
if self.vector[i] > self.result:
self.result = self.vector[i]
print("self", self, "result", self.result)
def result_after(self, seconds):
p = multiprocessing.Process(target=self.update_forever, name="update_forever", args=())
p.start()
p.join(seconds)
if p.is_alive():
p.terminate()
p.join()
print("self", self, "final result", self.result)
return self.result
if __name__ == "__main__":
import random, numpy as np
vector = np.random.rand(10000000)
maximizer = AnytimeAlgorithm(vector)
print(maximizer.result_after(0.01))
当我运行此类时,它表明,正如预期的那样,结果随时间增加。但是,返回值始终为0!这是一个典型的输出:
self <__main__.AnytimeAlgorithm object at 0x7f8e94de1cf8> result 0.420804014071
self <__main__.AnytimeAlgorithm object at 0x7f8e94de1cf8> result 0.444555804935
self <__main__.AnytimeAlgorithm object at 0x7f8e94de1cf8> result 0.852844624467
self <__main__.AnytimeAlgorithm object at 0x7f8e94de1cf8> result 0.915336332491
self <__main__.AnytimeAlgorithm object at 0x7f8e94de1cf8> result 0.964438367823
self <__main__.AnytimeAlgorithm object at 0x7f8e94de1cf8> result 0.975029317702
self <__main__.AnytimeAlgorithm object at 0x7f8e94de1cf8> result 0.975906346116
self <__main__.AnytimeAlgorithm object at 0x7f8e94de1cf8> result 0.987784181209
self <__main__.AnytimeAlgorithm object at 0x7f8e94de1cf8> result 0.996998726143
self <__main__.AnytimeAlgorithm object at 0x7f8e94de1cf8> result 0.999480015562
self <__main__.AnytimeAlgorithm object at 0x7f8e94de1cf8> result 0.999798469992
self <__main__.AnytimeAlgorithm object at 0x7f8e94de1cf8> final result 0
我的错误是什么?
当您在Python中使用多处理时,它实际上会创建一个新的独立Python过程,并运行您要求的任何内容。简化了API的事实,因此看起来,多线程不应该使您感到困惑。在主过程中,您创建一个AnytimeAlgorithm
对象。然后,您创建一个运行功能的Process
;这将创建一个新的过程并复制解释器的状态,因此您在新过程中也可以使用AnytimeAlgorithm
的副本,可以使用。但是,这两个对象不相同,它们甚至都不在同一过程中生活,因此它们无法(直接(共享任何信息。您对新过程中对象进行的更改仅影响该过程中的对象副本,而不是原始过程中的对象。
您可以检查有关如何在主过程和产生的文档之间共享信息的文档,例如使用管道,队列或共享内存,这可能是一个不错的选择:
import multiprocessing
import random
import numpy as np
class AnytimeAlgorithm:
def __init__(self, vector):
self.vector = vector
self.result = multiprocessing.Value('d', 0.0)
def update_forever(self):
while True:
i = random.randint(0, len(self.vector) - 1)
if self.vector[i] > self.result.value:
self.result.value = self.vector[i]
print("self", self, "result", self.result.value)
def result_after(self, seconds):
p = multiprocessing.Process(target=self.update_forever, name="update_forever", args=())
p.start()
p.join(seconds)
if p.is_alive():
p.terminate()
p.join()
print("self", self, "final result", self.result.value)
return self.result.value
if __name__ == "__main__":
import random, numpy as np
vector = np.random.rand(10000000)
maximizer = AnytimeAlgorithm(vector)
print(maximizer.result_after(0.1))
输出:
self <__mp_main__.AnytimeAlgorithm object at 0x0000017D26AB7898> result 0.01491873361800522
self <__mp_main__.AnytimeAlgorithm object at 0x0000017D26AB7898> result 0.060776471658675835
self <__mp_main__.AnytimeAlgorithm object at 0x0000017D26AB7898> result 0.7476611733129928
self <__mp_main__.AnytimeAlgorithm object at 0x0000017D26AB7898> result 0.9468162088782311
self <__mp_main__.AnytimeAlgorithm object at 0x0000017D26AB7898> result 0.9531978645650057
self <__mp_main__.AnytimeAlgorithm object at 0x0000017D26AB7898> result 0.9992671080742871
self <__mp_main__.AnytimeAlgorithm object at 0x0000017D26AB7898> result 0.999293465561661
self <__mp_main__.AnytimeAlgorithm object at 0x0000017D26AB7898> result 0.9996894825552965
self <__mp_main__.AnytimeAlgorithm object at 0x0000017D26AB7898> result 0.9998511378366163
self <__mp_main__.AnytimeAlgorithm object at 0x0000017D26AB7898> result 0.999933119926922
self <__main__.AnytimeAlgorithm object at 0x00000195FBDC7908> final result 0.999933119926922
0.999933119926922
请注意,由于过程间同步访问,使用Value
具有额外的开销。阅读文档,以了解锁定如何为此课程工作,并考虑以最小化对共享资源的访问的方式编写算法(例如,使用每个计算末尾编写的时间局部变量(。