Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
并行化两个玩家相互竞争的Python for循环(博弈论模拟)_Python_Multithreading_Parallel Processing_Multiprocessing_Game Theory - Fatal编程技术网

并行化两个玩家相互竞争的Python for循环(博弈论模拟)

并行化两个玩家相互竞争的Python for循环(博弈论模拟),python,multithreading,parallel-processing,multiprocessing,game-theory,Python,Multithreading,Parallel Processing,Multiprocessing,Game Theory,我正在用Python编写一个博弈论模拟。作为模拟的一部分,每一代都有两名玩家配对并相互比赛(每个玩家都是Player1或Player2类的一个实例)。稍微简化一下,代码如下所示: pool1 = [Player1() for _ in range(50)] pool2 = [Player2() for _ in range(50)] assignments = range(50) random.shuffle(assignments) pairs = [] for i, assignment

我正在用Python编写一个博弈论模拟。作为模拟的一部分,每一代都有两名玩家配对并相互比赛(每个玩家都是
Player1
Player2
类的一个实例)。稍微简化一下,代码如下所示:

pool1 = [Player1() for _ in range(50)]
pool2 = [Player2() for _ in range(50)]

assignments = range(50)
random.shuffle(assignments)

pairs = []
for i, assignment in enumerate(assignments):
    pairs.append((pool1[i], pool2[assignment]))

for player1, player2 in pairs:
    repeat = True
    while repeat:
        repeat = play_game(player1, player2)
收益作为玩家的属性保留。在每轮结束时,根据玩家的移动,游戏将继续或结束(
play\u game
将分别返回True或False)

如何使此代码并行运行?也就是说,我怎么能同时玩超过1对的游戏?我在谷歌上搜索了一下,找到了Python库,但我不知道如何将它应用到这段代码中


谢谢

我将创建一个类
游戏
,该类继承自
threading.Thread
,因此其行为类似于线程<代码>游戏类构造函数接受两个玩家对象和游戏的编号

number
是通过共享变量
resultList
将游戏结果返回主程序所必需的(列表在Python中是线程安全的)
resultList
是一个列表列表,每个
Game
实例根据其
编号将结果放入
resultList
的相应单元格中

每个
Game()
实例的
run()
方法在不同的线程中执行,因此所有游戏都是并行进行的

import threading
numOfGames = 10
resultList = [[] for x in xrange(numOfGames)]

class Game(threading.Thread):

    def __init__(self, player1, player2, number):
        threading.Thread.__init__(self)
        self.number = number
        self.player1 = player1
        self.player2 = player2

    def run(self):

        #Your game algorithm between self.player1 and self.player2 is here

        #Put game result into shared list
        resultList[self.number] = <result>

PS:我不建议使用多处理,因为创建一个进程会有很大的开销(需要分配堆栈等)。在您的情况下,多处理就足够了,因为您的应用程序不需要内存隔离。

仅对帖子上的评论进行评论(没有足够的评论代表),它可能会变慢,因为创建这么多进程会导致开销。除非play_游戏将是CPU密集型或长时间运行的,否则您可能不希望为此使用单独的进程。线程的启动强度通常较低(在Windows上比在Unix/Linux上更为真实,因为Unix/Linux将线程视为进程),并且可能更接近您所需要的

部分问题在于您对结果的使用。看起来play_游戏可以返回False并杀死循环,但是这个模型将不能与线程一起工作,因为它们将不再以线性方式执行。如果您只想运行所有这些功能,您可以进行更改

for player1, player2 in pairs:
    repeat = True
    while repeat:
        repeat = play_game(player1, player2)


一次为所有这些不同的配对启动线程。如果您想在其中一个线程没有返回True时杀死所有正在运行的线程,您需要查看线程之间的通信,并且您需要在主程序中有一个侦听器线程,以便在线程运行时读取线程的输出。

多线程和多处理是非常不同的,所以你应该先决定你想要哪一个。我对这两个都知之甚少。从我的搜索结果来看,似乎多处理更容易使用,对吗?如果不知道游戏功能中发生了什么,就很难确切地说该做什么。游戏中如何处理输出?您有多少内核可用?一个简单的解决方案是为每一对分支一个进程。这将导致50个进程。这取决于play_game()中发生的情况,这可能会很好,也可能会占用CPU。需要更多信息。这些策略表示为有限状态自动机。在play_game()中,这两种策略相互对抗(第一个玩家的移动被输入玩家2,玩家2通过决定是否继续玩或停止来响应)。每次移动后都会增加收益。它的重量很轻,这一步不需要大量的计算。我计划在EC2实例上运行这个。可能是4-8个内核(“vCPU”)。@sundance well通常
线程化
更容易使用,因为您不必担心进程间通信(您可能需要研究)。但是在CPython中,
线程
受全局解释器锁(更多研究)的约束,这意味着如果您的任务受CPU限制,它不会导致性能加速-事实上,它会导致速度减慢<代码>多处理
避开了这一限制,但可能会带来
线程化
不会带来的额外复杂性。玩游戏返回的“结果”实际上存储在玩家对象本身中(支付,每个玩家的属性,持有该值)。所以,我实际上不需要任何列表中的游戏结果。这能简化事情吗?当然,没问题。您的
玩家
对象将在所有游戏结束后保持其状态
Player
对象变量在Game.Run()中修改,但在所有线程连接后保留该值。”“结果列表”变得不必要了,谢谢您提供的信息。正如我刚才在另一个答案中所评论的,玩游戏返回的“结果”实际上存储在玩家对象本身中(支付,每个玩家的属性,持有该值)。所以,我实际上不需要任何列表中的游戏结果。这是否意味着我可以只运行
threading.Thread
,而不附加到列表中?是的,您可以。我将它们附加到列表中,然后执行join()操作的原因是强制应用程序等待所有游戏完成后再继续。我假设在游戏结束后,你所做的任何事情都会对这些对象进行操作,如果你不等待所有线程完成,或者以其他方式确保你正在处理的对象来自一个完成的线程,那么你最终会遇到竞争条件。
for player1, player2 in pairs:
    repeat = True
    while repeat:
        repeat = play_game(player1, player2)
thread_list = []
for player1, player2 in pairs:
    thread_list.append(threading.Thread(target=play_game,args=(player1,player2)))
for wait_thread in thread_list:
    wait_thread.join()