需要更快的数组复制

7
经过一番阅读,我发现在Java中复制数组的方法有所不同。对于我的应用程序,我有一个包含2D棋盘数组(8x8)的递归节点树。
通过分析测试,我找到了最好的方法是使用java.util.Arrays.copyOf(array)方法,该方法使用本地的System.arraycopy。
即使如此,我仍然花费了80%的时间来创建新的数组。如果有人有任何加速这个过程的想法,我会非常感激。也许使用64项数组而不是8x8会更快。我很快就会测试这个想法。

6
有没有一种方法可以只传递数组的引用而完全避免复制? - daniel gratzer
最好的方法显然是使用System.arraycopy,你已经使用过了,现在只剩下很少的选择,其中之一是通过删除空或空元素来缩小数组,你可以使用SparseMatrix类型的数据结构。 - Amit Deshpande
3
如果涉及到数组分配,你需要自己进行分配,使用一次单独的 new T[881000]。 - Joop Eggen
2
你是真的遇到了性能问题,还是只是想让你的应用程序更快,尽管它已经足够快了?如果是后者,那就不要做任何事情。 - JB Nizet
1
Oracle的不同Java实现都在内部使用本地方法进行数组复制。如果你最终要执行8个arraycopy,那么通过使用1d数组,实现自己的2d子脚本(例如@JoopEggen的评论),并进行单个arraycopy,可以获得性能提升。然而,可读性会受到影响。 - President James K. Polk
显示剩余3条评论
5个回答

3

如果你花费80%的时间复制数组,那么可能有两种情况:

  1. 数组复制速度太慢;
  2. 你除了复制数组几乎什么都没有做。

你的复制性能可能已经达到了尖端水平;考虑应用程序的架构,尝试减少复制数据的量。


3

1
我最近在这方面进行了调查(请参见我的答案Is there any way to create a primitive array without initialization?),它本可以被命名为“为什么Array.copyOf如此缓慢”或“为什么Java如此缓慢”,甚至向Oracle发送了RFE。主要想法是Java花费了太多时间进行无用的数组初始化。这就是Arrays.copyOf可能更快的原因。

没错,这只是为了证明概念,现在我们唯一能做的就是记住 new byte[n] 很昂贵。我打算编写一个 JNI CreateUninitializedByteArray 并看看这个想法在实际中如何运作。 - Evgeniy Dorofeev
JNI开销太高,很可能得不偿失。我认为你应该找到一种改进算法的方法(如下所述)。 - R.Moeller

1

你需要一种算法改进。(你是在做极小极大棋类算法吗?)

一种可能的方法是只复制每个8x8数组的引用,并为每个数组添加一个“共享”标志。然后,仅在实际更改数组时才复制数组。只要您没有更改所有数组,这将大大减少复制。

另一种变体是找到更紧凑的8x8数组表示方法(例如一些位运算技巧)。

您的数组条目包含什么?


0

感谢您的回复。一个8x8的数组本质上是9个数组分配和1个初始化。通过使用大小为64的数组而不是8x8,只需要一次分配,就可以跳过初始化。

然而,我将会研究其他提高速度的方法……因为更快的数组拷贝意味着我可以创建更多的节点:D。

谢谢大家


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接