2016-01-11 38 views
0

我在模擬CPU綁定任務。每個CPU限制任務計算800的階乘。每個CPU限制任務是一個由Thread執行的Runnable對象。當我增加線程數量(每個線程運行一個Runnable tak),然後我發現一些線程運行得如此之快以至於服務時間趨於零。我無法理解這種行爲。代碼如下。模擬具有固定工作量的CPU密集型任務

import java.math.BigInteger;  
public class CpuBoundJob implements Runnable {  
    public void run() {  
     BigInteger factValue = BigInteger.ONE; 
      long t1=System.nanoTime();  
      for (int i = 2; i <= 800; i++){ 
       factValue = factValue.multiply(BigInteger.valueOf(i)); 
      } 
     long t2=System.nanoTime();    
     System.out.println("Service Time(ms)="+((double)(t2-t1)/1000000)); 
    }  
} 

public class TaskRunner extends Thread { 
    CpuBoundJob job=new CpuBoundJob(); 
    public void run(){ 

    job.run(); 
    } 
} 

public class Test { 
int numberOfThreads=5; 
public Test(){ 
    for(int i=1;i<=numberOfThreads;i++){ 
     TaskRunner t=new TaskRunner(); 
     t.start(); 
     } 
} 
public static void main(String[] args) { 
    new Test(); 
    } 
} 

在5成一線的情況下,輸出是如下。

Service Time(ns)=28.765821 
Service Time(ns)=33.489663 
Service Time(ns)=29.19727 
Service Time(ns)=34.259404 
Service Time(ns)=37.347448 

在10個線程的情況下,輸出如下。

Service Time(ns)=45.647232 
Service Time(ns)=3.972654 
Service Time(ns)=23.494475 
Service Time(ns)=12.210069 
Service Time(ns)=19.382478 
Service Time(ns)=15.34706 
Service Time(ns)=54.769652 
Service Time(ns)=20.646827 
Service Time(ns)=3.28936 
Service Time(ns)=29.809905 
Service Time(ns)=60.798897 
Service Time(ns)=50.718839 
Service Time(ns)=2.727253 
Service Time(ns)=2.882779 
Service Time(ns)=63.864835 
Service Time(ns)=42.601425 
Service Time(ns)=4.029496 
Service Time(ns)=4.339761 
Service Time(ns)=79.396239 
Service Time(ns)=2.923832 
Service Time(ns)=5.773848 
Service Time(ns)=3.064359 
Service Time(ns)=2.446592 
Service Time(ns)=2.205802 
Service Time(ns)=2.212513 
Service Time(ns)=2.265408 
Service Time(ns)=82.51073 
Service Time(ns)=2.200276 
Service Time(ns)=2.289487 
Service Time(ns)=2.322645 
Service Time(ns)=2.201459 
Service Time(ns)=2.217644 
Service Time(ns)=2.197908 
Service Time(ns)=2.252381 
Service Time(ns)=13.564814 
Service Time(ns)=2.238171 
Service Time(ns)=2.199486 
Service Time(ns)=2.179355 
Service Time(ns)=2.237381 
Service Time(ns)=2.593041 
Service Time(ns)=2.444225 
Service Time(ns)=2.42054 
Service Time(ns)=38.745219 
Service Time(ns)=81.232565 
Service Time(ns)=19.612216 
Service Time(ns)=22.31381 
Service Time(ns)=59.521916 
Service Time(ns)=59.511258 
Service Time(ns)=54.439255 
Service Time(ns)=11.582434 

我無法理解2.4等的服務時間,有時服務時間下降到0.8。爲什麼線程運行固定數量的工作執行得這麼快?

+0

備註:1)合併'CpuBoundJob'和'TaskRunner'或者移除'implements Runnable''CpuBoundJob'。 ('Runnable'用於提交給Executor。)2)請正確格式化您的代碼。花括號的位置使其難以閱讀。 –

回答

2

你是如何開始這些測試?如果你每次都運行冷啓動,我懷疑JVM是「warming up」和Just In Time compiling的代碼。如果是這種情況,那麼帶有幾個線程的測試將作爲解釋代碼運行,並且以後的運行將被編譯,甚至以後的運行將根據以前的運行進行優化。 The JVM is magic that way

理念,使優化不太可能打:

  • 使用隨機數作爲工作參數(而不是循環索引)
  • 使用時間作爲工作參數(同上)
  • 擲在一些字符串連接
  • 通過與所述工作改變環的長度參數
+0

我應該在CpuBoundJob中使用哪些代碼無法通過JIT進行優化。我需要有一個固定數量的工作,總是在固定的時間內執行。 –

+0

你可以睡覺的線程。這不是工作,但返回之前需要一段固定的時間。模擬CPU限制。除非您想要某種其他原因使用CPU。也許最好不要使用JAVA,而是讓你的Java線程調用像pi-computing二進制的系統進程。 – Karl

+0

@FaisalBahadur答案更新了想法 –

0

最有可能的定時功能太不準確,以至於無法測量如此快速的操作。嘗試100000的階乘或類似的東西。

nanotime方法的文檔說,它不能保證提供精確到納秒:

此方法提供納秒精密,但不一定納秒的分辨率(即頻率變化值) - 無擔保除了分辨率至少和currentTimeMillis()一樣好之外。

1

它是口服可以肯定的是,JIT在某些時候開始並優化了代碼。首先嚐試運行實驗,首先對系統進行「預熱」,即對於N次迭代(您需要試驗什麼是N的好值),然後測量e。G:

public class Test { 

private int numberOfThreads; 
private int warmUpIterations; 

public Test(int numberOfThreads, int warmUpIterations) { 
    this.numberOfThreads = numberOfThreads; 
    this.warmUpIterations = warmUpIterations; 
} 

public void runTests() { 
    for (int i = 0; i < warmUpIterations; i++) { 
     test(); // don't collect timing here 
    } 

    test(); // collect timing here 
} 

private void test() { 
    for (int i = 0; i < numberOfThreads; i++) { 
     TaskRunner t = new TaskRunner(); 
     t.start(); 
    } 
} 

public static void main(String[] args) { 
    new Test(10, 10000).runTests(); 
} 

}

而且打印的統計數據,從內run()是有問題的,可考慮在一些收集積累他們,並打印出來,一旦測試完成。

+0

我應該在CpuBoundJob中使用哪些代碼無法通過JIT進行優化。我需要有一個固定數量的工作,總是在固定的時間內執行 –