java - 并行排序比串行排序慢

标签 java sorting

<分区>

我正在阅读 Java 8 中的新功能,其中之一是新的 Arrays.parallelSort() 方法。我做了一些测试,对 double 组和一个字符串进行排序,对于字符串,parallelSort 慢得多。

下面是一个字符串测试方法的内容:

    final int size = 10000;
    final String[] values1 = new String[size];
    final String[] values2 = new String[size];
    for (int i = 0; i < size; i++) {
        values1[i] = Integer.toString(i);
        values2[i] = values1[i];
    }
    Collections.shuffle(Arrays.asList(values1));
    Collections.shuffle(Arrays.asList(values2));
    final Comparator<String> comparator = (o1, o2) -> o2.compareTo(o1);

    long startTimeInNano = System.nanoTime();
    Arrays.sort(values1, comparator);
    long endTimeInNano = System.nanoTime();
    System.out.println("Arrays.sort: totalTimeInMicro= " + ((endTimeInNano - startTimeInNano)/1000));

    //parallel sort with java 8
    startTimeInNano = System.nanoTime();
    Arrays.parallelSort(values2,comparator);
    endTimeInNano = System.nanoTime();
    System.out.println("Arrays.parallelSort: totalTimeInMicro= " + ((endTimeInNano - startTimeInNano)/1000));

结果是:

Arrays.sort: totalTimeInMicro= 11993

Arrays.parallelSort: totalTimeInMicro= 89823

我还在另一台计算机上尝试了这段代码,结果是一样的(25608 对 808660)。我运行测试的计算机有一个 i5-2500 CPU。您知道我为什么会得到这种结果吗?

最佳答案

这个基准测试几乎没有告诉您任何信息。微基准测试最重要的事情是

  • 让 JIT 有机会通过多次运行测试来优化代码
  • 使用不同的输入尺寸
  • 打印一些结果,以防止 JIT 优化整个调用

还有一些要考虑的要点 - 事实上,很多要考虑的要点。你应该咨询How do I write a correct micro-benchmark in Java?了解更多信息。

要获得真正“深刻”的信息,您应该使用像 Caliper 这样的工具或 JMH .但即使不费吹灰之力,也可以创建一个微基准,粗略地显示实际性能如何。因此,一种最简单的微基准测试形式可能如下所示:

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;

public class ParallelSortSpeedTest
{
    public static void main(String[] args)
    {
        for (int size=100000; size<=1000000; size+=100000)
        {
            final String[] values1 = new String[size];
            final String[] values2 = new String[size];
            for (int i = 0; i < size; i++) {
                values1[i] = Integer.toString(i);
                values2[i] = values1[i];
            }
            Collections.shuffle(Arrays.asList(values1));
            Collections.shuffle(Arrays.asList(values2));
            final Comparator<String> comparator = (o1, o2) -> o2.compareTo(o1);

            testSort(values1, comparator);
            testParallelSort(values2, comparator);
        }
    }

    private static void testSort(
        String array[], final Comparator<String> comparator)
    {
        long startTimeInNano = System.nanoTime();
        Arrays.sort(array, comparator);
        long endTimeInNano = System.nanoTime();
        System.out.println("Arrays.sort        : totalTimeInMicro= " + 
            ((endTimeInNano - startTimeInNano)/1000)+", first "+array[0]);
    }

    private static void testParallelSort(
        String array[], final Comparator<String> comparator)
    {
        long startTimeInNano = System.nanoTime();
        Arrays.parallelSort(array, comparator);
        long endTimeInNano = System.nanoTime();
        System.out.println("Arrays.parallelSort: totalTimeInMicro= " + 
            ((endTimeInNano - startTimeInNano)/1000)+", first "+array[0]);
    }

}

考虑到启动和运行 JMH 基准测试的工作量与结果的可靠性之间的权衡,这是一个合理的选择。这个测试会打印类似的东西

...
Arrays.sort        : totalTimeInMicro= 530669, first 999999
Arrays.parallelSort: totalTimeInMicro= 158227, first 999999

至少表明并行排序应该更快。

关于java - 并行排序比串行排序慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29234203/

相关文章:

c - 选择排序在排序后将指针保持在正确位置时出现问题

java - 如何验证字符串数组中的用户输入?

java - 通过java应用程序在windows机器上设置日期和时间的最佳方法

java - 具有渲染属性的jsf commandlink和commandbutton不会触发actionlistener

algorithm - 基数排序是否适用于位数不同的数字?

javascript - 使用 javascript 重新组织 DOM 元素

ios - 如何在 Swift 中从 NSmutableArray 的索引之一(lat lng 坐标)对 NSmutableArray 进行排序

java - 看不懂Java普通类库的用法

java - 如何仅使用应用程序打开文件

arrays - VBA:根据另一个数组对数组进行排序