2016-03-17 30 views
1

我實施巴恩斯小屋算法爲N體問題的一個多線程溶液線程的數目。多線程應用程序運行時增加與

Main類執行以下操作

public void runSimulation() { 
     for(int i = 0; i < numWorkers; i++) { 
      new Thread(new Worker(i, this, gnumBodies, numSteps)).start(); 
     } 
     try { 
      startBarrier.await(); 
      stopBarrier.await(); 
     } catch (Exception e) {e.printStackTrace();} 
} 

的bh.stop-和bh.startBarrier是CyclicBarriers設置開始和停止時間以System.nanoTime();達到時(屏障行動)。

工人運行方法:

public void run() { 
    try { 
     bh.startBarrier.await(); 

     for(int j = 0; j < numSteps; j++) { 
      for(int i = wid; i < gnumBodies; i += bh.numWorkers) { 
       bh.addForce(i); 
       bh.moveBody(i); 
      } 
      bh.barrier.await(); 
     } 
     bh.stopBarrier.await(); 
    } catch (Exception e) {e.printStackTrace();} 
} 

addForce(I)經過一棵樹,做一些計算。它不影響任何共享變量,因此不使用同步。 O(NlogN)。

moveBody(I)不會在一個元件上的計算並且不使用同步。上)。

當達到bh.barrier,與所有機構一棵樹建成(屏障作用)。

現在來解決問題。運行時隨線程數的增加而線性增加。 運行時用於gnumBodies = 240,numSteps = 85000和四芯:

  • 1螺紋= 0.763
  • 2個線程= 0.952
  • 3線程= 1.261
  • 4線程= 1.563

爲什麼運行時不會隨着使用的線程數量而減少?

編輯:添加硬件信息

+0

我不認爲我們可以說沒有看到'addForce'和'moveBody'的代碼實際上做了什麼有用的東西。 –

回答

1

你在運行什麼硬件?運行多線程有其開銷,因此將您的任務分解爲小的子任務可能不值得。

此外,請嘗試使用ExecutorService而不是線程。這樣你可以使用線程池而不是爲每個任務創建一個實際的線程。硬件無法處理更多的線程是沒有用的。

它也看起來像每個線程將做同樣的工作。可以這樣嗎?當創建一個工人時,你每次除了i以外都使用相同的參數。

+0

我已經嘗試了ExcecutorService以及完全相同的結果。我的挫折使我嘗試了其他的東西:) 至於循環,如果你仔細檢查for循環,並且我有4個線程 for(int i = wid; i ChristianG

+0

爲什麼你有startBarrier?所有線程都需要等待對方啓動嗎? bh指的是什麼類,它是如何實現的?你可以發佈完整的代碼,以便我們可以更清楚地瞭解發生了什麼? –

0

多線程不會增加執行速度,除非你也有多個CPU內核。

線程做數學計算,可以全速運行

如果只有一個CPU核心,如果你在一個線程或多個線程運行的計算是完全一樣的。在多線程中運行不會帶來性能上的好處,但會帶來線程切換的開銷,所以實際上總體性能會有所下降。

如果有多個可用的CPU內核,那麼線程可以物理並行多達核心數量運行。這意味着4-8個線程可能在當今的桌面硬件上運行良好。

線程等待IO和被停用

主題意義,如果你不這樣做數學計算,而是做一些涉及緩慢I/O,如網絡,文件或數據庫。當一個線程等待IO時,另一個線程可以使用相同的CPU內核,而不是佔用程序的運行時間。這就是爲什麼Web服務器和數據庫解決方案的工作線程數多於CPU內核的原因。

避免不必要的同步

儘管如此,您測量顯示控制同步錯誤。 我想你應該從線程代碼中刪除所有xxbarrier.await()。 我不確定xxBarriers vs. System nanopime的目標是什麼,但是任何不必要的synchornization都可能導致性能下降。而不是計算,你在xxxBarriers等待。

+0

該應用程序運行在具有4個內核的英特爾®酷睿™i7-3612QM上。 – ChristianG

+0

我猜到了類似的東西:)所以如果你將線程的數量增加到4個,你期望總執行時間更短是正確的。時間消除障礙! :) –

+0

沒有你提到的類型的I/O。 第一個屏障調用,即startBarrier,只是設置startTime並且只調用一次。與stopBarrier同樣的事情。 對bh.barrier的調用是必要的,因爲當所有線程都到達此障礙時,會創建一個新的樹,該樹將在以下循環中使用,等等。所以障礙需要在那裏:) – ChristianG

0

您的員工獨立完成同樣的工作numWorker次。 唯一的共享對象是你的CyclicBarrier。 await()等待所有奇怪隊在這個障礙上等待。隨着工作人員數量的增加,花費更多時間在await()

+0

他們不是。如果檢查爲循環密切 對(INT I = WID; I ChristianG

0

如果您有多個核心或者超線程可用,那麼運行多線程將受益於底層硬件。

如果只有一個核心存在,如果您的應用程序涉及至少一個非CPU密集型工作,如與人類的交互,則多線程可以給予「感知」的好處。與現代CPU相比,人類非常緩慢。因此,如果您的應用程序需要從人類獲得多個輸入並進行處理,則可以在兩個線程中分開輸入和計算。當人類提供輸入時,部分計算可以在另一個線程中完成。因此整體時間的改善。

如果您的應用程序必須進行計算並且不存在硬件多線程支持,則最好使用單線程。您的「計算」已經在管道中排隊並且CPU將已經以(幾乎)最大速度運行。多線程將需要上下文切換時間,這將增加執行計算所花費的時間。

+1

超線程和多核並不意味着同樣的事情,並且不提供相同級別的物理併發性,恐怕:) –

+0

@GeeBee同意。但是,即使在純CPU密集型應用的情況下,不會超線程提供一些優勢嗎?謝謝 –

+1

沒問題,*一些*優勢。基本上它允許其他線程重用未使用的執行單元。如果正在運行的線程執行不同的操作,例如一個線程執行乘法操作,另一個執行加法操作(儘管這是一個相當粗略的例子),這是有益的。但是,如果每個人都想要繁殖,則線程將在(有限數量)的執行單元上排隊。 (請注意,今天的處理器都是超標量的,在指令執行級實現隱式併發,因此有多個執行單元 - 但這與線程問題無關。) –

0

當我用更少的步驟運行具有更多數量的主體的應用程序時,應用程序按預期縮放。所以問題可能是屏障的開銷!

相關問題