java - 如何加速Java中的数组交集?

标签 java arrays performance intersection

下面的数组排序时没有重复(包含唯一的正整数)小尺寸(小于 5000)和交集(见下文)被调用十亿次,因此任何微优化都很重要。这articleC 中很好地描述了如何加速以下代码语言。

int i = 0, j = 0, c = 0, la = a.length, lb = b.length;
intersection = new int[Math.min(la, lb)];
while (i < la && j < lb) {
    if (a[i] < b[j]) i++;
    else if (a[i] > b[j]) j++;
    else {
        intersection[c] = a[i];
        i++; j++; c++;
    }
}
int[] intersectionZip = new int[c];
System.arraycopy(intersection, 0, intersectionZip, 0, c);

我猜在 Java 中是不可能调用那些低级指令的。但是他们提到“可以使用无分支实现来改进这种方法”。怎么做呢?使用 switch ?或者可以替代 a[i] < b[j] , a[i] > b[j]a[i] == b[i]与整数操作数的二元运算比较?

二进制搜索方法(具有复杂性 O(la log(lb)) )并非如此,因为 la不是 <<lb .有趣的是如何改变 if声明。

最佳答案

我不认为您可以做很多事情来提高 Java 代码的性能。但是,我会注意到它做的事情与 C 版本不同。 C 版本将交集放入调用者预先分配的数组中。 Java 版本自己分配数组......然后在完成后重新分配并复制到一个较小的数组。

我想,您可以更改 Java 版本以对输入数组进行两次传递,第一次传递计算出输入数组需要有多大……但它是有助于还是阻碍将取决于输入。

您可能还可以针对其他特殊情况进行优化;例如如果一个数组中可能有很长的数字,而另一个数组中的那个范围内没有任何数字,您也许可以“乐观地”尝试一次性跳过多个数字;即,将 ij 增加一个大于 1 的数字。


But they mention that "it is possible to improve this approach using branchless implementation". How one would do it? Using switch?

不是 Java 开关...或条件表达式,因为它们在转换为 native 代码时都涉及分支。

我认为他指的是这样的东西:Branchless code that maps zero, negative, and positive to 0, 1, 2

FWIW 尝试在 Java 中做这种事情是个坏主意。问题在于,像这样的棘手代码序列的性能取决于硬件架构、指令集、时钟计数等细节,这些细节因平台而异。 Java JIT 编译器的优化器可以很好地优化您的代码……但是如果您包含棘手的序列:

  1. 它们将如何转换为 native 代码并不明显或不可预测,并且
  2. 您可能会发现这种棘手的做法实际上会阻碍 JIT 编译器本来可以进行的有用优化。

话虽如此,Java 的某些 future 版本可能包含一个 super 优化器并非不可能……就像上面链接的问答中提到的那样……能够自动生成无分支序列。但请记住, super 优化的执行成本非常高。

关于java - 如何加速Java中的数组交集?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16460807/

相关文章:

Java String换行,有特定逻辑,无字符串格式

java - 错误 Appenders 包含无效元素或属性 "NoSql"

Chrome 中的 Javascript 未返回与 Internet Explorer 相同的数组长度

无法使用我认为应该是编译时常量的内容来初始化静态数组

Linux Ubuntu Tomcat Best Config 避免内存不足

java - HTML 标签未反射(reflect)在 Gxt Grid 中

Java无缘无故地锁定文件

ios - 如何在调用索引后从数组中永久删除项目?

c++ - if 语句位于循环内,反之亦然

performance - JavaFX runlater 规范和性能