2017-07-16 58 views
-1

我有一個關於複製一個0結尾的字符串的問題:更快的方式比的memcpy複製0結尾的字符串

const char * str = "Hello World !"; 
size_t getSize = strlen(str); 
char * temp = new char[getSize + 1]; 

...我知道我可以使用此功能

memcpy(temp, str, getSize); 

但我想用我自己的複製功能,有這樣

int Count = 0; 
while (str[Count] != '\0') { 
    temp[Count] = str[Count]; 
    Count++; 
} 

兩個辦法的是真實的和成功的行動。現在我要檢查它在10 milions倍和的memcpy做這個動作

const char * str = "Hello World !"; 
size_t getSize = strlen(str); 
for (size_t i = 0; i < 10000000; i++) { 
    char * temp = new char[getSize + 1]; 
    memcpy(temp, str, getSize); 
} 

,這是我自己的方式

const char * str = "Hello World !"; 
    size_t getSize = strlen(str); 
    for (size_t i = 0; i < 10000000; i++) { 
     char * temp = new char[getSize + 1]; 
     int Count = 0; 
     while (str[Count] != '\0') { 
      temp[Count] = str[Count]; 
      Count++; 
     } 
    } 

420毫秒和第二完成第一過程完成650毫秒 ...爲什麼?這兩種方式都是一樣的!我想用我自己的函數而不是memcpy。有什麼辦法讓我自己的方式更快(memcpy速度快,也許速度更快)? 我如何更新我自己的方式(while)使其更快或與memcpy相等?

完整的源

int main() { 

    const char * str = "Hello world !"; 
    size_t getSize = strlen(str); 

    auto start_t = chrono::high_resolution_clock::now(); 
    for (size_t i = 0; i < 10000000; i++) { 
     char * temp = new char[getSize + 1]; 
     memcpy(temp, str, getSize); 
    } 
    cout << chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_t).count() << " milliseconds\n"; 


    start_t = chrono::high_resolution_clock::now(); 
    for (size_t i = 0; i < 10000000; i++) { 
     char * temp = new char[getSize + 1]; 
     int done = 0; 
     while (str[done] != '\0') { 
      temp[done] = str[done]; 
      done++; 
     } 
    } 
    cout << chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_t).count() << " milliseconds\n"; 

    return 0; 
} 

結果:

482毫秒
654毫秒

+2

你如何衡量執行時間? –

+3

依靠數組末尾的「\ 0」字符,與「memcpy()」不同。如果你想處理這種情況,那麼只有你用'strcpy()'纔可能比使用自己的函數更好(實現中可能會使用某些技巧,使得它比實現更快)。 – user0042

+3

爲什麼你認爲你可以智取編譯器標準庫的創建者? – PaulMcKenzie

回答

1

...這兩方面的方法是一樣的!

不,他們不是:

  1. memcpy()不檢查每個字符包含'\0'與否。
  2. 可能有更多的優化,由實施者做得比你在天真方法有

這是不可能的,你的方法可以比memcpy()更快。

+1

請刪除您的答案,並將其作爲評論發佈。 –

+2

@ Khaled.K爲什麼這樣?我的回答很好地解釋了差異。 – user0042

+0

那麼memcpy如何創建一個從str到temp的副本? – myOwnWays

3

用自己的代替庫函數往往導致性能低下。

memcpy代表一個非常基本的記憶操作。因此,它的作者進行了高度優化。與「天真」實現不同,只要有可能,庫版本就會一次移動多個字節,並在可用的平臺上使用硬件協助。此外,編譯器本身「知道」memcpy和其他庫函數的內部工作方式,並且可以在編譯時知道長度的情況下完全優化它們。

注:你的實現具有strcpy,不memcpy語義。

+0

好的,我想知道如何! 100%的memcpy也檢查每個字符! (逐一複製...),爲什麼它必須更快! – myOwnWays

+1

@myOwnWays閱讀庫實現源代碼和/或在發佈(優化)構建中檢查生成的彙編器。 –

+3

@myOwnWays _「memcpy檢查每個字符!」_咦?不,它沒有。 – user0042

0

看到你沒有使用指針,並將你正在做的事(strcpy)與memcpy進行比較清楚地表明你是初學者,而且正如其他人已經指出的那樣,你很難勝任一個像編碼圖書館。

但我會給你一些提示來優化你的代碼。 我簡要介紹了Microsoft的C標準庫實現(稱爲C運行時庫),並且它們在組裝中執行速度比在C中快。所以這是速度的一個要點。在大多數具有32位總線的32位體系結構中,CPU可以在一個請求中從內存中獲取32位信息到內存(假設數據正確對齊),但即使您需要16位或8位,它仍然需要提出這1個請求。所以使用你的機器的字大小可能會給你一些加速。

最後,我想把你的注意力引向SIMD。如果你的CPU提供它,你可以使用它並獲得額外的速度。 MSCRT也有一些SSE2優化選項。

在過去,我不得不編寫優於我的庫實現的代碼,因爲我有一個特定的需求或特定類型的數據,我可以優化它,但它可能具有一些教育價值,除非專門所需時間最好花在實際代碼上,而不是花在重新實現庫函數上。

相關問題