Java 使用minimax时,有多少线程可以用于tic-tac-toe?
让我们以5x5 tic tac toe为例。 假设现在轮到我的人工智能了。 那么Java 使用minimax时,有多少线程可以用于tic-tac-toe?,java,algorithm,minimax,Java,Algorithm,Minimax,让我们以5x5 tic tac toe为例。 假设现在轮到我的人工智能了。 那么 我做了25次移动(当然,如果合法的话,基本上是在每个单元) 移动) 为每个移动创建一个线程(总共25个线程(最多)) 在每次移动时调用minimax函数 然后当所有结果都来自每个线程时 比较得分,选择得分最高的动作 以下是我的问题: 使用25个线程是否有效?使用25个线程意味着什么 是不是快了25倍(很可能不是)?这取决于什么?当然是在计算机上,但是我怎么知道基于计算机资源可以使用多少线程呢 如果我使用了太多
- 我做了25次移动(当然,如果合法的话,基本上是在每个单元) 移动)
- 为每个移动创建一个线程(总共25个线程(最多))
- 在每次移动时调用minimax函数
- 然后当所有结果都来自每个线程时
- 比较得分,选择得分最高的动作
- 使用25个线程是否有效?使用25个线程意味着什么
- 是不是快了25倍(很可能不是)?这取决于什么?当然是在计算机上,但是我怎么知道基于计算机资源可以使用多少线程呢
- 如果我使用了太多的线程(我猜什么都没有…),会发生什么李>
另一个要考虑的是java线程在典型的JVM上创建是昂贵的。因此,除非一个线程(在其生命周期内)做了足够的工作,否则您在创建线程上花费的时间可能比在计算中使用多个核所获得的时间还要多
最后,您可能会发现工作并不是均匀地分布在所有线程上,这取决于您的最小-最大算法。。。以及游戏状态如果我试图实现这一点,我会首先将其实现为单线程应用程序,然后:
- 对其进行基准测试,以确定连续运行时计算一个更高的值需要多长时间
- 对其进行分析以消除任何瓶颈
- 重新进行基准测试,看看它是否已经足够快了
要回答您的直接问题: 使用25个线程是否有效 可能不会。只有当你有那么多内核的时候,它才会有效率(不太可能!)。即使这样,如果并行运行得到的比线程相关开销带来的损失更多,那么使用大量线程也只能获得很好的加速。(换句话说,这取决于您使用这些线程的效率。) 使用25个线程意味着什么 我假设您的意思是,您已经创建并启动了25个线程,或者是显式地,或者是使用一些现有的线程池实现 但底线是,如果您有(比如)4个内核,那么这25个线程中最多有4个可以同时执行。其他线程将等待 是不是快了25倍(很可能不是)?这取决于什么?当然是在计算机上,但是我怎么知道基于计算机资源可以使用多少线程呢 限制性能的主要因素是内核的数量。见上文 如果我使用了太多的线程(我猜什么都没有…),会发生什么 太多的线程意味着您使用了更多的内存,这使得您的应用程序运行较慢,因为内存带宽竞争、物理内存页竞争、额外的垃圾收集。这些因素依赖于应用程序和平台,难以量化;i、 预测或测量 根据应用程序的性质(即,具体实现算法的方式),过多的线程可能会导致额外的锁争用和线程上下文切换。这也会使您的应用程序速度变慢
在没有看到实际代码的情况下,预测将会发生什么是不可能的。但是内核的数量为您提供了一个理论上的加速上限。如果您有4个内核,那么多线程的加速比就不能超过4倍。如果您使用线程,那么为了防止内存浪费,只需在第一次调用mini max时使用它们,然后将线程的结果合并以获得输出。如果您使用25个线程或某个数量如此之大的线程,这将是一种浪费,因为可用的内核远小于此数量,因此您可以在不同的状态下一次只调度与可用内核等效的线程,并在最后合并所有结果 以下是伪代码:-
int miniMax(State,Player,depth) {
// normal minimax code
}
State ParaMiniMax(State,Player) {
int totalThreads = Runtime.getRuntime().availableProcessors());
NextStates = getNextStates(State);
while(NextStates.size()>0) {
k = totalThreads;
while(k>0 && NextStates.size>0) {
//Schedule thread with nextState. with run calling miniMax with other player
//Store (score,state) in Result List
k--;
NextStates.removeTop();
}
wait(); // waits for threads to complete
}
if(player==max) {
return(maxScore(Result).State);
}
else return(minScore(Result).State);
}
您应该只使用与机器的内核数相等的线程数。将任务安排到这些线程上是另一回事。因此,给出的线程答案是可以的,但在我看来,他们忽略了minimax搜索的alpha-beta修剪功能 如果您从当前位置为每一个“下一步”启动一个线程,那么让这些线程相互对话对于正确编写来说是缓慢而痛苦的。但是,如果他们不能互相交谈,那么你就不能从alpha-beta修剪中获得深度提升,直到更深一层 这将影响结果的效率 对于提高计算时间的一般情况,最好的情况往往是每个核1个线程,如果所有任务的时间都相似,则简单地将任务分配给线程(例如矩阵乘法),或者有一组任务,每个线程在完成其当前任务时都会抓取下一个未启动的线程。(这有一些锁定任务,但如果与resol相比,这些任务较小
xxx..
.xx..
..x..
.....
.....
12321
24542
35653
24542
12321