2012-02-15 112 views
1

我不得不解碼一些字節數組(原始數據)。它可以由基本數據類型(int,unsigned int,char,short等)組成。根據定義的結構,我需要解釋它們。下面是示例:如何減少CPU使用量?

struct testData 
{ 
int a; 
char c; 
}; 
    unsigned char** buf = {0x01,0x00,0x00,0x00,0x41} 
    example byte array(in little endian) : 0100000041 

    should give decoding like : a = 1, c = 'A' 

示例數據可能非常大,並且示例結構(例如testData)可以包含200 - 3000個字段。 如果我使用我鑄造讀取來自BUF **適當的數據和設置指針象下面這樣:

int a = *(reinterpret_cast<int*>(*buf); 
    *buf += 4; 
    char c = **buf; 
    *buf += 1; 

我的CPU使用率是相當高的,如果需要解碼的Fileds的數量都很高。例如:

struct testData 
    { 
    int element1; 
    char element2; 
    int element3; 
     ... ... 
    ... ... 
     short element200; 
    char element201; 
    char element202; 
    } 

是否有降低CPU負荷,以及保持非常快速的解碼的方法嗎?

我有兩個限制:

  1. 「結構可以包含填充字節。」
  2. 我無法控制如何定義結構。結構也可以包含嵌套元素。

回答

5
int a = *(reinterpret_cast<int*>(*buf); 

不要使用reinterpret_cast。您對編譯器說謊並強制未對齊的訪問。更糟的是,你是從編譯器隱藏它需要優化你的代碼的信息 - 指針實際上是字符。相反,代碼你的意思儘可能簡單,那就是:

int a=static_cast<int>(*buf[0]) | 
    (static_cast<int>(*buf[1])<<8) | 
    (static_cast<int>(*buf[2])<<16) | 
    (static_cast<int>(*buf[3])<<24); 

這是簡單,清晰,你真正想要的東西。編譯器在優化它時沒有問題。 (而且,它會不管你的工作平臺的字節序。)

+0

是不是讀取逐字節和移位操作將比使用強制轉換讀取多個字節慢? – learningstack 2012-02-22 04:05:22

+0

@learningstack也許,也許不是。它可能取決於平臺。但我不必擔心,因爲我使用了好的編譯器,我不會對他們撒謊。對於編譯器來說,這個轉換關係到對齊並將其誘發爲產生錯誤的代碼。 – 2012-02-22 04:43:46

2

你應該能夠簡單地將結構映射到緩衝區中,只要結構包裝妥當:

#pragma pack(push, 1) 
struct testData 
    { 
    int element1; 
    char element2; 
    int element3; 
     ... ... 
    ... ... 
     short element200; 
    char element201; 
    char element202; 
    } 
#pragma pack(pop) 

你也應該申報該結構以明智的方式排列,請不要混合使用int,然後使用char,然後使用int ...然後,如果您在對齊的緩衝區中讀取數據,只需簡單地將緩衝區轉換爲testData*就可以訪問所有成員。這樣你就可以避免所有這些無償的副本。如果你閱讀正向結構(p->element1,然後閱讀p->element2,然後p->element3等)hardware prefetch應該踢,並給予了很大的提升。

進一步的增強需要實際測量熱點。另外,從圖書館查閱這本書並閱讀它:The Software Optimization Cookbook

+0

非常感謝您的評論。但我有兩個限制: – learningstack 2012-02-16 09:07:45

+0

非常感謝您的評論。但我有兩個約束: 1.「結構可以包含填充字節。」 2.我無法控制如何定義結構。結構也可以包含複合元素(結構,聯合,數組等)。 – learningstack 2012-02-16 09:31:54

1

除了David Schwartz的迴應,你可以通過編寫一些輔助模板函數來清理它。我會建議這樣的事情(未經測試)。

template<typename T> 
const unsigned char * read_from_buffer(T* value, const unsigned char * buffer); 

template<> 
const unsigned char * read_from_buffer<int>(int* value, const unsigned char * buffer) 
{ 
    *value = static_cast<int>(*buf[0]) | 
    (static_cast<int>(*buf[1])<<8) | 
    (static_cast<int>(*buf[2])<<16) | 
    (static_cast<int>(*buf[3])<<24); 
    return buffer+4' 
} 

template<> 
const unsigned char * read_from_buffer<char>(char * value, const unsigned char * buffer) 
{ 
    *value = *buffer; 
    return buffer+1; 
} 

struct TestData 
{ 
    int a; 
    char c; 
}; 

int main() 
{ 
    unsigned char buf[] = {0x01,0x00,0x00,0x00,0x41}; 
    unsigned char * ptr = buf; 

    TestData data; 
    ptr = read_from_buffer(&data.a, ptr); 
    ptr = read_from_buffer(&data.c, ptr); 
} 

您可以封裝此更進一步,並添加錯誤檢查等,你就會有一樣的界面,一個漂亮的二進制流。

+0

是不是讀取逐個字節和移位操作會比使用轉換讀取多個字節慢? – learningstack 2012-02-22 04:03:08