2014-04-09 21 views
2

我們正在做一些性能優化我們的項目,並與我來到了以下方法探查:加快字節解析的可能性?

private int CalculateAdcValues(byte lowIndex) 
{ 
    byte middleIndex = (byte)(lowIndex + 1); 
    byte highIndex = (byte)(lowIndex + 2); 

    // samples is a byte[] 
    retrun (int)((int)(samples[highIndex] << 24) 
     + (int)(samples[middleIndex] << 16) + (int)(samples[lowIndex] << 8)); 
} 

這種方法已經相當快,每執行〜1μs的,但它被稱爲每秒〜100.000倍所以它佔用CPU的10%左右。

有沒有人有一個想法如何進一步改進這種方法?

編輯:

目前的解決方案:

fixed (byte* p = samples) 
{ 
    for (; loopIndex < 61; loopIndex += 3) 
    { 
     adcValues[k++] = *((int*)(p + loopIndex)) << 8; 
    } 
} 

這需要時間< 40%,那麼之前(每次通話 「全法」 採取了〜爲35μs前後〜爲13μs現在) 。該for -loop actualy需要更多的時間則calcualtion現在...

+0

爲什麼強制類型'byte'?你需要減少指數mod 256嗎?由於移位已將值擴展爲「int」,所以對「int」的強制轉換是無用的。 – CodesInChaos

回答

3

看到你有一個友好的字節序,去unsafe

unsafe int CalculateAdcValuesFast1(int lowIndex) 
{ 
    fixed (byte* p = &samples[lowIndex]) 
    { 
    return *(int*)p << 8; 
    } 
} 

在x86上約30%的速度。我希望沒有多少收穫。在x64上時約爲40%。

正如@CodeInChaos建議:

var bounds = samples.Length - 3; 
    fixed (byte* p = samples) 
    { 
    for (int i = 0; i < 1000000000; i++) 
    { 
     var r = CalculateAdcValuesFast2(p, i % bounds); // about 2x faster 
     // or inlined: 
     var r = *((int*)(p + i % bounds)) << 8; // about 3x faster 
     // do something 
    } 
    } 


unsafe object CalculateAdcValuesFast2(byte* p1, int p2) 
{ 
    return *((int*)(p1 + p2)) << 8; 
} 
+1

我認爲如果您將調整層級中的某一級別修改爲更高,則收益會更大。 – CodesInChaos

+0

如果'lowIndex == samples.Length-3'與OP的代碼不同,那麼您的代碼具有未定義的行爲。它也依賴於系統是小端。 – CodesInChaos

+0

@CodesInChaos:這就是爲什麼我說這是尾數友好的:)沒有,沒有看到任何不確定的行爲。它只是不會拋出異常,如果你走出界限,就像安全版本一樣。但你應該已經在照顧''for'條件了。 – leppie

5

我強烈懷疑,鑄造byte後,你的索引被轉換回int反正在數組索引操作使用。這將是便宜的,但可能不完全免費。所以擺脫演員陣容,除非你正在使用byte轉換來有效地獲得0到255範圍內的索引。在這一點上,你也可以擺脫單獨的局部變量。

此外,由於移位操作僅在int及更高類型上定義,因此您的演員名稱爲int爲空操作。

最後,使用|可能會快於+

private int CalculateAdcValues(byte lowIndex) 
{ 
    return (samples[lowIndex + 2] << 24) | 
      (samples[lowIndex + 1] << 16) | 
      (samples[lowIndex] << 8); 

} 

(爲什麼有沒有在低8位是不是故意的注意,結果將最終被否定,如果samples[lowIndex + 2]有它的頂部?位集 - 是否可以?)

+2

比以前快了50%,但是我們用來自leppie的'unsafe'解決方案,因爲它更快... – ChrFin

+0

@「爲什麼底部8位沒有任何東西?」:我們有32位整數,但我們只有從硬件中獲得最高24位來節省帶寬,因爲它足夠滿足我們的需求。 – ChrFin

0

可能下面可以快一點。我已經刪除了轉換爲整數。

 var middleIndex = (byte)(lowIndex + 1); 
     var highIndex = (byte)(lowIndex + 2); 

     return (this.samples[highIndex] << 24) + (this.samples[middleIndex] << 16) + (this.samples[lowIndex] << 8);