亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

有沒有理由不使用 Java 8 的 parallelSort?

有沒有理由不使用 Java 8 的 parallelSort?

江戶川亂折騰 2023-03-02 15:54:20
我正在閱讀這個Arrays.sort關于 Java和Java 之間差異的問題Arrays.parallelSort,這個問題已經有幾年了。令我驚訝的是,只有一個問題提到了使用 ; 的任何缺點parallelSort。也就是說,如果您使用大量 CPU,加速會降低。假設您不在某種專門的單線程環境中,是否應該始終選擇parallelSort?有沒有理由不這樣做?請注意,上述問題的答案之一提到,如果元素少于 4096 個,則parallelSort仍然調用sort。
查看完整描述

4 回答

?
料青山看我應如是

TA貢獻1772條經驗 獲得超8個贊

使用有一些缺點Arrays.parallelSort

  • 它使用ForkJoinPool.commonPool()并且會與默認使用它的其他功能戰斗(例如parallel()在流上)

  • 線程池Arrays.parallelSort的使用是不可配置的(只能通過增加公共池線程數量在全局級別上使用)

  • 它在小數據集上表現更差(數組通常包含很少的元素,JDK 甚至承認,例如,大多數元素ArrayList 在其整個生命周期中都保持為空,這節省了相當多的內存和 CPU 時間,因為不實例化永遠不會填充的數組)

另一個軼事場景:假設您實現了一些需要排序的紙牌游戲。將多個游戲并行執行非常容易,而不是將一次運行的排序機制并行化,后者可能只占用整個游戲循環的一小部分。您現在失去了一種簡單的并行化方法(例如,在遺傳算法的上下文中運行游戲時)。

但是,是的,如果您碰巧有大型數組并且排序是應用程序運行時的重要組成部分,請使用Arrays.parallelSort.

編輯:如果給定的數組少于 4096 個元素,即使Arrays.parallelSort切換到正常排序:這都是為了顯示意圖——如果可能的話,你想要一個并行排序,它與僅僅調用 . 具有不同的含義sort。挑剔一點:它確實在小數組上表現更差,因為它必須額外檢查數組是否包含少于 4096 個元素,以及一些關于公共池線程數的其他檢查(開銷當然可以忽略不計):) .


查看完整回答
反對 回復 2023-03-02
?
至尊寶的傳說

TA貢獻1789條經驗 獲得超10個贊

stream()這與何時使用vs 的問題沒有太大區別parallelStream()——這取決于您擁有多少數據。當然,大多數時間,當并行排序 10 個元素時,將被底層的線程框架(文檔未指定)消耗,而不是排序本身。


但是您也想知道為什么引入 IMO 此類方法。硬件正在(已經移動?)轉向許多CPU,而不是更多GHz,因此對于任何希望在未來 20 年內仍然存在的語言來說,并行處理只是一個正常過程。


至于你實際需要多少數據才能表現出性能,parallelSort再加上sort知道我們至少 MIN_ARRAY_SORT_GRAN + 1需要獲得任何潛在的好處;編寫一個適當的測試來證明對于這個特定的設置和運行,你至少需要X數字,并不那么復雜。您還必須考慮到某些數組可能已經排序(進一步解釋),而某些數組可能完全未排序(5,4,3,2,1例如),這會給第二個數組帶來一些懲罰。


獲取一些隨機數據并進行測試:


@Warmup(iterations = 10)

@OutputTimeUnit(TimeUnit.NANOSECONDS)

@Measurement(iterations = 2, time = 2, timeUnit = TimeUnit.SECONDS)

public class ParallelSort {


    public static void main(String[] args) throws Exception {

        Options opt = new OptionsBuilder()

            .include(ParallelSort.class.getName())

            .build();


        new Runner(opt).run();

    }


    @Benchmark

    @BenchmarkMode(Mode.AverageTime)

    @Fork(1)

    public int[] parallel(ParallelSortExecutionPlan plan) {

        Arrays.parallelSort(plan.ints());

        return plan.ints();

    }


    @Benchmark

    @BenchmarkMode(Mode.AverageTime)

    @Fork(1)

    public int[] nonParallel(ParallelSortExecutionPlan plan) {

        Arrays.sort(plan.ints());

        return plan.ints();

    }

}



@State(Scope.Benchmark)

public class ParallelSortExecutionPlan {


    @Param(value = {"10", "100", "1000", "10000", "100000", "1000000"})

    private int howMany;


    private int[] ints;


    public static void main(String[] args) {

    }


    @Setup(Level.Invocation)

    public void setUp() {

        ints = new int[howMany];

        for (int i = 0; i < howMany; ++i) {

            ints[i] = ThreadLocalRandom.current().nextInt();

        }

    }


    int[] ints() {

        return ints;

    }

}

請注意第二個類正在使用@Setup(Level.Invocation)(如果你知道一點JMH)——這是一個非常鋒利的工具;Invocation但我使用它是因為我希望每個方法都有一個未排序的數組。否則,如果Trial將被使用例如 - 只有第一次調用將是一個未排序的數組,該@Benhcmark方法的所有其他調用都已經排序。為了好玩,您可以將該單行更改為@Setup(Level.Trial)例如并查看結果,它們將毫無意義。


運行此顯示:


Benchmark                 (howMany)  Mode  Cnt         Score   Error  Units


ParallelSort.nonParallel         10  avgt    2       128.847          ns/op

ParallelSort.parallel            10  avgt    2       116.656          ns/op


ParallelSort.nonParallel        100  avgt    2      1956.746          ns/op

ParallelSort.parallel           100  avgt    2      1963.335          ns/op


ParallelSort.nonParallel       1000  avgt    2     32162.611          ns/op

ParallelSort.parallel          1000  avgt    2     31716.915          ns/op


ParallelSort.nonParallel      10000  avgt    2    423531.663          ns/op

ParallelSort.parallel         10000  avgt    2    201802.609          ns/op


ParallelSort.nonParallel     100000  avgt    2   6503511.987          ns/op

ParallelSort.parallel        100000  avgt    2   1363169.661          ns/op


ParallelSort.nonParallel    1000000  avgt    2  69058738.586          ns/op

ParallelSort.parallel       1000000  avgt    2  13469112.930          ns/op

對我來說幾乎是一個非常期待的輸出。


查看完整回答
反對 回復 2023-03-02
?
HUX布斯

TA貢獻1876條經驗 獲得超6個贊

不,我會對足夠小的陣列說不。設置線程的開銷不會導致明顯的加速。

關鍵是“夠小”。它不會對所有問題都有相同的答案。

永遠不應該應用教條,除非是在這個教條規則的情況下。就像我們唯一不應該容忍的是不寬容一樣。某處存在波普爾悖論。


查看完整回答
反對 回復 2023-03-02
?
GCT1015

TA貢獻1827條經驗 獲得超4個贊

除了公共池使用和可優化的最小大小等原因之外,如果您通常有許多事務需要并行進行排序,則您可能也不需要并行化單個排序。

在那種情況下,您可以通過拆分工作包來避免開銷。(然而,具有可配置并行工作的可控執行器也適用于多線程提交——您只需增加停放線程和上下文切換的數量)


查看完整回答
反對 回復 2023-03-02
  • 4 回答
  • 0 關注
  • 145 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號