2015-06-19 20 views
3

我發現自己調整了一段代碼,其中使用memcpy複製了內存,第三個參數(大小)在編譯時已知。memcpy在編譯時已知大小

函數調用memcpy的消費者做一些與此類似:現在

template <size_t S> 
void foo() { 
    void* dstMemory = whateverA 
    void* srcMemory = whateverB 
    memcpy(dstMemory, srcMemory, S) 
} 

,我本來期望的是,memcpy內在很聰明,認識到這一點:

foo<4>() 

。 ..可以用函數中的memcpy替換32位整數賦值。然而,令人驚訝的我發現自己看到了> 2倍加速這樣做:

template<size_t size> 
inline void memcpy_fixed(void* dst, const void* src) { 
    memcpy(dst, src, size); 
} 


template<> 
inline void memcpy_fixed<4>(void* dst, const void* src) { *((uint32_t*)dst) = *((uint32_t*)src); } 

,改寫foo到:

template <size_t S> 
void foo() { 
    void* dstMemory = whateverA 
    void* srcMemory = whateverB 
    memcpy_fixed<S>(dstMemory, srcMemory) 
} 

兩種測試都在鐺(OS X)與-O3。我真的希望memcpy固有的更聰明的情況下,在編譯時已知的大小。

我的編譯器標誌是:

-gline-tables-only -O3 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer

我要求太多了C++編譯器的或者是有我錯過了一些編譯器標誌?

+0

的問題是,的memcpy實際上是一個C函數,不知道有關模板什麼... –

+0

的memcpy是一個函數,所以的3個輸入不具有在編譯時是已知的。由於假定對齊訪問並且沒有函數調用開銷,所以使用整數賦值具有性能優勢。然而,假設對齊的訪問可能導致UB,如果這種假設不成立的話。 – user3528438

+1

memcpy是一個內在的。現代C編譯器當然不只是一個正常的功能。嘗試添加對齊信息(可能是對齊提示)。 – usr

回答

5

memcpy是不一樣的*((uint32_t*)dst) = *((uint32_t*)src)

memcpy可以處理未對齊的內存。

順便說一句,大多數現代編譯器都會用合適的代碼發射替換已知大小的memcpy。對於小尺寸,它通常會排出諸如rep movsb之類的東西,在大多數情況下,這可能不夠快。

如果您發現您的特定情況下,你獲得2倍的速度,你認爲你需要加快步伐,你可以自由地得到你的手髒(有明確的意見)。

+0

我的記憶是對齊的。我如何提示它正確? –

+0

@ThomasKejser對於一次調用它可能是,但如果您在另一個大小爲4的類型上使用它,編譯器應該如何爲它生成另一個模板? – Wolf

+1

@ThomasKejser你可以專注於[alignment_of](http://en.cppreference.com/w/cpp/types/alignment_of)。 – nwp

1

如果源和目標緩衝區作爲函數參數設置:

template <size_t S> 
void foo(char* dst, const char* src) { 
    memcpy(dst, src, S); 
} 

然後鐺++ 3.5.0使用memcpy只有當S是大,但它使用當movl指令S = 4

但是,您的源地址和目標地址不是此函數的參數,這似乎可以防止編譯器進行這種激進的優化。

相關問題