java – 什么时候Spliter停止分裂?

前端之家收集整理的这篇文章主要介绍了java – 什么时候Spliter停止分裂?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我明白 there is overhead in setting up处理一个并行流,并且在单个线程中的处理速度更快,如果有少量项目或每个项目的处理速度很快.

但是,trySplit()是否有类似的门槛,将问题分解成更小的块就会适得其反?我正在考虑类似于合并排序切换到最小块的插入排序.

如果是,阈值取决于trySplit()和consuming在tryAdvance()过程中的一个项目的相对成本?考虑一个拆分操作比推进一个数组索引分割一个有序的multiset排列要复杂得多.有没有一个惯例让客户在创建并行流时指定拆分的下限,这取决于消费者的复杂性? Spliterator可以用来估计下限本身的启发式?

或者,将Spliter的下限设置为1,总是安全的,让工作窃取算法考虑选择是否继续分割?

解决方法

一般来说,你不知道在尝试Advisor或forEachRemaining的消费者中做了多少工作.流管道和FJP都不知道这一点,因为它取决于用户提供的代码.它可以比分割程序快得多或慢得多.例如,您可能有两个元素的输入,但每个元素的处理需要一个小时,因此拆分此输入是非常合理的.

我通常尽可能多地分割输入.有三个技巧可以用来改善分裂:

>如果难以均匀分割,但您可以跟踪(或至少粗略估计)每个子部分的大小,可以自由分割.流的实现将在更大的部分进一步分裂.不要忘记SIZED和SUBSIZED的特点.
>将分割的重要部分移动到下一个tryAdvance / forEachRemaining调用.例如,假设你有一个已知的排列数,而在trySplit中,你将会跳到其他排列.这样的事情

public class MySpliterator implements Spliterator<String> {
    private long position;
    private String currentPermutation;
    private final long limit;

    MySpliterator(long position,long limit,String currentPermutation) {
        this.position = position;
        this.limit = limit;
        this.currentPermutation = currentPermutation;
    }

    @Override
    public Spliterator<String> trySplit() {
        if(limit - position <= 1)
            return null;
        long newPosition = (position+limit)>>>1;
        Spliterator<String> prefix = 
                 new MySpliterator(position,newPosition,currentPermutation);
        this.position = newPosition;
        this.currentPermutation = calculatePermutation(newPosition); // hard part
        return prefix;
    }

    ...
}

将硬件部分移动到下一个tryAdvance调用,如下所示:

@Override
public Spliterator<String> trySplit() {
    if(limit - position <= 1)
        return null;
    long newPosition = (position+limit)>>>1;
    Spliterator<String> prefix = 
             new MySpliterator(position,currentPermutation);
    this.position = newPosition;
    this.currentPermutation = null;
    return prefix;
}

@Override
public boolean tryAdvance(Consumer<? super String> action) {
    if(currentPermutation == null)
        currentPermutation = calculatePermutation(position); // hard part
    ...
}

这样,硬件部分也将与前缀处理并行执行.>如果您目前没有这么多的元素(例如,不到10个),并且分配被要求,那么提升到一半的元素收集到数组中可能是很好的,然后创建一个基于数组的分割器对于这个前缀(类似于在AbstractSpliterator.trySplit()中完成).在这里,您可以控制所有代码,因此您可以提前测量trySplit的正常速度,而不是tryAdvance,并且在切换到基于阵列的拆分时估计阈值.

原文链接:https://www.f2er.com/java/125194.html

猜你在找的Java相关文章