如何更快地克隆阵列?
在国际象棋AI程序中,我有一个必须执行的功能,然后撤消了一步。
为了做到这一点,我需要保存一堆包含有关板上当前情况的数据的备份(例如碎片所在的位置,哪些碎片正在受到攻击,或者如果国王受到检查),然后进行移动,最后重置数组。
我使用的代码是这样的:
int[] piecesBackup = pieces.Clone() as int[];
MakeMove();
pieces = piecesBackup.Clone() as int[];
// I've also tried this
int[] piecesBackup = new int[pieces.Length];
pieces.CopyTo(piecesBackup, 0);
MakeMove();
pieces = new int[piecesBackup.Length];
piecesBackup.CopyTo(pieces, 0);
此代码重复了数千次,并且需要很长时间。我怀疑这里的耗时操作是克隆/复制操作。
我想不出任何更好的方法来解决这个问题:这真的是复制数组内容的唯一方法吗?有什么办法可以简单地使用int [] potebackup = picts
然后pipter = potebackup
?
In a chess AI program, I have a function that has to do and then undo a move.
In order to do this, I need to save a backup of a bunch of arrays containing data about the current situation on the board (like where the pieces are, which pieces are under attack or if a king is in check, for example), then make the move and finally reset the arrays.
The code I'm using is like this:
int[] piecesBackup = pieces.Clone() as int[];
MakeMove();
pieces = piecesBackup.Clone() as int[];
// I've also tried this
int[] piecesBackup = new int[pieces.Length];
pieces.CopyTo(piecesBackup, 0);
MakeMove();
pieces = new int[piecesBackup.Length];
piecesBackup.CopyTo(pieces, 0);
This code is repeated thousands of times and it takes very long to do so. I suspect that the time consuming operation here is the cloning/copying operation.
I can't think of any better approach to this problem: is this really the only way to copy the contents of an array? Is there any way I could simply use int[] piecesBackup = pieces
and then pieces = piecesBackup
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我想您的大部分时间都花在分配物体或清理垃圾中。尽管GC处理大多数方案,但很高的频率分配可能会出现问题。但是,与往常一样,我建议一些分析以确认实际上是这种情况。关于性能,很容易猜测错误。
我会尝试将董事会状态适应不变的结构。由于这是一种值类型,因此您可以完全删除任何堆的分配。
我的国际象棋知识有点生锈,但是如果我没记错的话,随时可以发挥最大的32件作用,每件零件都有64个可能的位置。因此,我们应该能够用32个字节代表整个板,并剩下一些可能的用途。 32字节对于结构而言并不是不合理的大小,应该非常快地创建副本。
使用结构可能需要添加所有32件作为单独的字段,这可能是更多的编写代码,但是优化的代码通常并不漂亮。我还建议您阅读生活的文章对游戏状态优化的一些观点。
I would guess that most of your time is spent allocating objects or cleaning up garbage. While the GC handles most scenarios quite well, very high frequency allocation can be problematic. But as always, I would recommend some profiling to confirm that this is actually the case. It is very easy to guess incorrectly with regards to performance.
I would try to fit the board state within an immutable struct. Since this is a value type you could get away with removing any heap allocations at all.
My chess knowledge is a bit rusty, but if I'm not mistaken there can be max 32 pieces in play at any time, and 64 possible positions for each piece. So we should be able to represent the entire board with 32 bytes, with some bits left over for other possible uses. 32 bytes is not an unreasonable size for a struct, and should be very fast to create a copy of.
Using a struct might require adding all 32 pieces as separate fields, and this might be more code to write, but well optimized code is often not pretty. I would also recommend reading Eric Lipperts articles on Game of Life for some perspective on game state optimization.
考虑每次执行副本时重复使用阵列而不是分配新阵列。分配一个新数组需要时间,然后还有一些垃圾收集将在某个时候出现,以清除不再使用的旧数组。
阵列重复使用是我使用的方法,其性能结果良好。这是示例代码,该代码演示了代码重复使用的时间约为分配新数组的时间。
我的机器(YMMV)产生的输出。
Consider reusing the arrays instead of allocating new arrays each time the copy is performed. Allocating a new array takes time and then there is also the garbage collection that will come along at some point to clear away the old array no longer being used.
Array reuse is an approach that I have used with good performance result. Here is example code to that demonstrates code reuse taking about half as much time as allocating new arrays.
The resulting output from my machine (ymmv).
您才是正确的,因为您使用了国际象棋板的天文差代表。您可能需要在国际象棋游戏中存储一系列可以高达40亿个整数的原因?您有64个正方形,总共有32件。
至于您的分析,最多的时间可能是通过分配和释放(GC)所有这些巨大的阵列来获取的时间。您应该使用
arraypool<>
或MemoryPool<>
,或者只是具有正确尺寸的普通旧结构。You are correct only in that you are using an astronomically bad representation of a chess board. What possible reason would you possibly have to store an array of integers that can go up to 4 billion in a chess game? You have 64 squares and up to 32 pieces total.
As to your analysis, the most time is probably taken by allocating and freeing (GC) all those gigantic arrays. You should be using
ArrayPool<>
orMemoryPool<>
instead, or just plain old structures that have the correct size.