2012-01-19 46 views
10

考慮這個非常簡單的代碼:爲什麼相同的代碼在線程中執行得更快?

uses Diagnostics; 

const 
    ITER_COUNT = 100000000; 

procedure TForm1.btn2Click(Sender: TObject); 
var 
    val: Double; 
    i: Integer; 
begin 
    sw := TStopwatch.StartNew; 

    val := 1; 
    for i := 0 to ITER_COUNT - 1 do 
    begin 
    val := val + i; 
    val := val - i; 
    val := val * 10; 
    val := val/10; 
    end; 

    sw.Stop; 

    mmo1.Lines.Add(Format('Simple completed in %D ms. Result: %G', 
    [sw.ElapsedMilliseconds, val])); 
end; 

這種簡單的循環在我的電腦上毫秒執行。現在,如果我寫相同的代碼,只是使用不同的線程:

procedure TForm1.btn3Click(Sender: TObject); 
begin 
    sw := TStopwatch.StartNew; 
    TThread.CreateAnonymousThread(
    procedure 
    var 
     val: Double; 
     i: Integer; 
    begin 
     val := 1; 
     for i := 0 to ITER_COUNT- 1 do 
     begin 
     val := val + i; 
     val := val - i; 
     val := val * 10; 
     val := val/10; 
     end; 

     sw.Stop; 

     TThread.Queue(nil, procedure 
     begin 
      mmo1.Lines.Add(Format('Async completed in %D ms. Result: %G', 
      [sw.ElapsedMilliseconds, val])); 
     end); 
    end 
).Start; 
end; 

這種方法,做同樣的,但在不同的線程中毫秒執行! (在Delphi XE中編譯的Release配置處於活動狀態)無論我有多少次迭代,我都會在線程中發現〜25%的增益。爲什麼這樣呢?它不應該是相同的結果嗎?

編輯: 經過進一步調查後,我發現可能是這個原因是Windows 7操作系統。在Windows 7機器上,主線程中的簡單循環比異步版本執行速度慢25%!我甚至嘗試在使用Windows XP模式的同一臺Windows 7電腦上運行這個相同的項目,然後兩個結果相同 - 〜3000ms!我完全迷失在這裏...... Windows 7對主線程的處理是什麼?

+0

無法重現,我的筆記本電腦(〜2600毫秒)執行時間相同。 – kludg

+0

對我來說也沒有什麼不同。 1947年和1949年ms在我的機器上,但由於我仍然使用Delphi 5作爲我的主要開發環境,因此我學到了一些新的東西,+1。 –

+0

你在什麼樣的操作系統下進行測試? – Linas

回答

12

奇怪的確,但也許是因爲一些偏移c.q.對準。

也許匿名線程中的變量是正確對齊的,而另一個不是。 您可以嘗試添加一些虛擬變量以更改爲偏移量,或者如果您有Delphi XE2,請嘗試一些不同的code alignment

+0

我試圖用虛擬變量(在某些測試中約5000毫秒)放慢第一個版本的速度,但不能使速度超過〜4000ms ...但這不會影響異步版本... – Linas

+0

@Linas Make確保'val'始終與8字節邊界對齊。例如,通過調用GetMem而不是在堆棧上分配它。 –

+0

@DavidHeffernan這就是訣竅。如果我手動將我的'Double'變量與'GetMem'循環對齊,按預期執行。問題是爲什麼Delphi在單獨的匿名線程中正確執行此操作,而不是在主線程中執行此操作? – Linas

相關問題