如果實時 CPU 一次只執行一項任務,那么多執行緒與單處理器系統中的異步編程(就效率而言)有何不同?
例如,我們必須從 1 數到 IntegerMax。在我的多核機器的以下程式中,兩執行緒最終計數幾乎是單執行緒計數的一半。如果我們在單核機器上運行它會怎樣?有什么辦法可以達到同樣的結果嗎?
class Demonstration {
public static void main( String args[] ) throws InterruptedException {
SumUpExample.runTest();
}
}
class SumUpExample {
long startRange;
long endRange;
long counter = 0;
static long MAX_NUM = Integer.MAX_VALUE;
public SumUpExample(long startRange, long endRange) {
this.startRange = startRange;
this.endRange = endRange;
}
public void add() {
for (long i = startRange; i <= endRange; i ) {
counter = i;
}
}
static public void twoThreads() throws InterruptedException {
long start = System.currentTimeMillis();
SumUpExample s1 = new SumUpExample(1, MAX_NUM / 2);
SumUpExample s2 = new SumUpExample(1 (MAX_NUM / 2), MAX_NUM);
Thread t1 = new Thread(() -> {
s1.add();
});
Thread t2 = new Thread(() -> {
s2.add();
});
t1.start();
t2.start();
t1.join();
t2.join();
long finalCount = s1.counter s2.counter;
long end = System.currentTimeMillis();
System.out.println("Two threads final count = " finalCount " took " (end - start));
}
static public void oneThread() {
long start = System.currentTimeMillis();
SumUpExample s = new SumUpExample(1, MAX_NUM );
s.add();
long end = System.currentTimeMillis();
System.out.println("Single thread final count = " s.counter " took " (end - start));
}
public static void runTest() throws InterruptedException {
oneThread();
twoThreads();
}
}
輸出:
Single thread final count = 2305843008139952128 took 1003
Two threads final count = 2305843008139952128 took 540
uj5u.com熱心網友回復:
對于純粹受 CPU 限制的操作,您是正確的。大多數 (99.9999%) 的程式需要進行輸入、輸出和呼叫其他服務。這些比 CPU 慢幾個數量級,因此在等待外部操作的結果時,作業系統可以在時間片中調度和運行其他(許多其他)行程。
硬體多執行緒主要在滿足 2 個條件時受益:
- CPU 密集型操作;
- 可以有效地劃分為獨立的子集
或者您有許多不同的任務要運行,這些任務可以有效地分配給多個硬體處理器。
uj5u.com熱心網友回復:
在我的多核機器的以下程式中,兩執行緒最終計數幾乎是單執行緒計數的一半。
當應用程式使用兩個內核時,這就是我對有效基準的期望。
但是,查看您的代碼,我對您獲得這些結果感到有些驚訝……如此可靠。
您的基準測驗沒有考慮 JVM 預熱效果,尤其是 JIT 編譯。
您的基準測驗
add方法可能會被 JIT 編譯器優化以完全擺脫回圈。(但至少計數被“使用”......通過列印出來。)
我想你很幸運……但我不相信這些結果對于所有版本的 Java 都可以重現,或者如果你調整了基準。
請閱讀這個:
- 如何在 Java 中撰寫正確的微基準測驗?
如果我們在單核機器上運行它會怎樣?
假設如下:
- 您重寫了基準以更正上述缺陷。
- 您在硬體??超執行緒1已禁用2的系統上運行。
然后......我希望它需要兩個執行緒的時間是一個執行緒版本的兩倍多。
問:為什么是“超過”?
A:因為啟動一個新執行緒有很大的開銷。根據您的硬體、作業系統和 Java 版本,它可能超過一毫秒。當然,如果您反復使用和丟棄執行緒,所花費的時間會很長。
有什么辦法可以達到同樣的結果嗎?
不知道你在這里問什么。但是,如果您要問如何在多核機器上模擬一個核的行為,您可能需要在作業系統級別執行此操作。見https://superuser.com/questions/309617用于Windows和https://askubuntu.com/questions/483824的Linux版本。
1 -超執行緒是一種硬體優化,其中單核的處理硬體支持(通常)兩個超執行緒。每個超執行緒都有自己的暫存器組,但它與另一個超執行緒共享功能單元,例如 ALU。因此,這兩個超執行緒的行為(通常)類似于兩個內核,只是它們可能會更慢,具體取決于精確的指令組合。一個典型的作業系統將對待,就好像它是一個普通的核心超執行緒。超執行緒通常在啟動時啟用/禁用;例如,通過 BIOS 設定。
2 - 如果啟用了超執行緒,那么在像這樣的 CPU 密集型計算中,兩個 Java 執行緒的速度可能不會比一個快兩倍……這是由于各個內核上的“另一個”超執行緒可能導致速度變慢。有人提到基準測驗很復雜嗎?
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/340831.html
