【问题标题】:Parallel Mergesort benchmarking - determining threshold foundParallel Mergesort 基准测试 - 确定找到的阈值
【发布时间】:2019-04-30 14:23:45
【问题描述】:

我正在尝试确定停止细分我的 Mergesort 实现的合理阈值。

但是,我得到的结果是阈值应该在 1078 之间,考虑到 java 使用的默认阈值,这是荒谬的大约是 8192。它基本上告诉我细分几乎总是不好的,并且更高的阈值更好,因为它执行的分割更少。

它目前所做的工作是对一个大小为 108、随机范围为 01000 的浮点数数组进行排序。对每个测试的阈值重复使用相同的随机数组。

public class ParallelMergeSort extends SortStrategy {

    @Override
    public long sort(float[] a, int cores, int threshold) {
        System.gc();
        long start = System.nanoTime();
        RecursiveAction mainTask = new SortTask(a, 0, a.length - 1);
        SortTask.threshold = threshold;
        ForkJoinPool pool = new ForkJoinPool(cores);
        pool.invoke(mainTask);
        return System.nanoTime() - start;
    }

    private static class SortTask extends RecursiveAction {
        private float[] a;
        private int left, right;
        private static int threshold;

        SortTask(float[] a, int left, int right) {
            this.a = a;
            this.left = left;
            this.right = right;
        }

        @Override
        protected void compute() {
            if (left < right) {
                if ((right - left) < threshold) {
                    Arrays.sort(a, left, right + 1);
                } else {
                    int mid = (left + right)/2;
                    invokeAll(
                        new SortTask(a, left, mid),
                        new SortTask(a, mid + 1, right)
                    );
                    // Merge
                    int n1 = mid - left + 1;
                    int n2 = right - mid;
                    float a1[] = new float[n1];
                    float a2[] = new float[n2];
                    // Fill sub arrays
                    for (int i = 0; i < n1; ++i)
                        a1[i] = a[left + i];
                    for (int j = 0; j < n2; ++j)
                        a2[j] = a[mid + 1 + j];
                    // Sort and merge
                    int l = 0, r = 0, o = left;
                    while (l < a1.length && r < a2.length) {
                        if (a1[l] <= a2[r])
                            a[o++] = a1[l++];
                        else
                            a[o++] = a2[r++];
                    }
                    // Merge remaining
                    while (l < a1.length)
                        a[o++] = a1[l++];
                    while (r < a2.length)
                        a[o++] = a2[r++];
                }
            }
        }
    }
}

我知道由于 JIT,JVM 可能不可靠,但它应该只影响前几次迭代,不是吗?寻求有关算法的建议或为什么我的结果与我的预期相差甚远。

【问题讨论】:

标签: java parallel-processing benchmarking mergesort forkjoinpool


【解决方案1】:

最佳阈值是允许并行运行的线程数与系统中的内核数相同。

如果你的系统有cores 核心,阈值应该是 test 应该被初始化为

SortTask.threshold = cores > 0 ? (a.length + cores - 1) / cores : a.length;

由于最后几个合并阶段不能并行运行,因此速度提升将小于内核数量。

由于您正在对包含 108 个元素的数组进行排序,因此最佳阈值确实介于 107 和 108 之间,除非您拥有超过 10 个核心。

【讨论】:

  • 这只是 Mergesort 的情况,因为它将子数组分成两个大小相等的部分。如果使用 Quicksort,partition 更不稳定,阈值也会不同,不是吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-03
  • 1970-01-01
  • 2017-07-18
  • 2023-04-05
  • 1970-01-01
  • 2012-10-12
  • 2011-09-10
相关资源
最近更新 更多