Re: [問題] 怎麼提高效率?
這比memcpy快 可以快個三到四倍,調用方法與memcpy一樣
不做restricted保護
#include <emmintrin.h> /*SSE2*/
#define DIV16(VAL) ((VAL)>>4)
#define MUL16(VAL) ((VAL)<<4)
#define MEMCPY( PDST, PSRC, SIZE)
sse2_memcpy( (PDST), (PSRC), (SIZE))
void sse2_memcpy(void *pDst, void *pSrc, size_t size)
{
if(pDst == pSrc)
return ;
unsigned int i;
unsigned int nLoops;
char *pcDst, *pcSrc;
__m128i *pMovSrc, *pMovDst;
pMovDst = (__m128i*)(pDst);
pMovSrc = (__m128i*)(pSrc);
nLoops = DIV16((unsigned int)size);
__m128i _miTemp;
for(i = 0; i < nLoops; i++){
_miTemp = _mm_loadu_si128(pMovSrc);
_mm_storeu_si128( pMovDst, _miTemp);
pMovDst++;
pMovSrc++;
}
pcDst = (char*)(pMovDst);
pcSrc = (char*)(pMovSrc);
for(i = MUL16(nLoops); i< size; i++)
*pcDst++ = *pcSrc++;
}/*sse_memcpy*/
※ 引述《tropical72 (藍影)》之銘言:
: ※ 引述《heymei0421 (heymei)》之銘言:
: : 小弟目前用ubuntu為作業系統
: : 用google所提供的工具來量測performance
: : 好不容易搞了一個下午 總算把程式中各函式所執行的時間百分比弄出來
: : 如下圖:
: : http://ppt.cc/ueyv
: 我看不到這東西,請釋放權限。
: : void
: : my_memcpy (void *target, void *source, int size)
: : {
: : int i;
: : unsigned char *target_ptr = target;
: : unsigned char *source_ptr = source;
: : for (i = 0; i < size; i++)
: : {
: : *(target_ptr + i) = *(source_ptr + i);
: : }
: : }
: 如果你可以用 memcpy 的話就用它,它的速度正常的話會比自己寫快上2~3倍不是問題,
: 它放在 memory.h / string.h 裡面,不行調用的話才有必要自己寫。
: 一般而言在寫低階動作時,若「去掉 compiler 優化能力」,有幾個部份是值得注意的,
: (i) 盡可能使用前置
: (ii) 另一為盡可能減少陣列索引之計算
: (iii) 程式碼可以展開的話就盡可能展開 (很可笑對吧 ? 但它是事實..)
: 所以你的程式碼暫修如下
: typedef unsigned char byte;
: void cpy1(void* target, void* source, int size)
: {
: byte *Src=(byte*)source;
: byte *Des=(byte*)target;
: while(size) {
: *Des++ = *Src++;
: --size;
: }
: }
: 這樣就避開了計算 Des[i] / Src[i] 所需時間,如果要再快一點點的話,
: 「考慮」要不要弄個非標準的做法。
: void cpy2(void* target, void* source, int size)
: {
: byte *Src = (byte*)source;
: byte *Des = (byte*)target;
: byte *Src_End = (byte*)source + size;
: while(Src!=Src_End) /* 使用比較運算子取代了遞減運算子 */
: *Des++ = *Src++;
: }
: 非標準的地方在於 byte *Src_End = (byte*)source + size;
: 正常而言,指標 + size 這動作並不保證,但大多 compiler (一些面試題也基於此假設)
: 是從 source 移動 size 個 byte 大小。會不會更快不一定,
: 要去查「比較」和「遞減」所使用的週期數。
: 截至目前為止,其實改的都只是小部份,但有個較大的部份沒改到,
: 如果可以一次 4 bytes / 8 bytes 複制,速度會更快,
: 多出來的部份再慢慢 1 bytes / 1 bytes 複制。
: 這裡演示基於標準作法,要非標準的作法可再自己嚐試
: void cpy3(void* target, void* source, size_t size)
: {
: word *Wsrc_s = (word*)source;
: word *Wdes_s = (word*)target;
: byte *Bsrc_s;
: byte *Bdes_s;
: // 處理 4 bytes
: while(size>4){
: *Wdes_s++ = *Wsrc_s++;
: size-=4;
: }
: // 處理 < 4 bytes
: Bsrc_s = (byte*)(Wsrc_s);
: Bdes_s = (byte*)(Wdes_s);
: while(size) {
: *Bdes_s++ = *Bsrc_s++;
: --size;
: }
: }
: 基本上用到 4bytes 一次複製觀念速度就夠快了,
: 另外有個比較 kuso 的方式你可以參考
: 先建立一個 struct, 裡面直接丟 byte trunk[256], byte trunk[1024] 等
: struct 做 assigned 時,裡面的 trunk 會直接複制,
: 但速度怎樣將會相依於 compiler 實作之能力,會不會比較快不得而知,
: 但以我手中 vc2010 , debug mode 下測,這方式是最快的 (開 256),
: 在 size 較大情況下,速度比你原本方式快 5 倍以上 (看 N 值),
: 但最終還是打不過 memcpy (記得它 "應" 是用組語寫的!)
: 完整的測試程式碼參考如連結 http://ppt.cc/a;Bv
: 結果如下參考。
: N 787654321
: cpy1 : 453 arr2=arr1 (check) --> memcpy
: cpy2 : 3610 arr2=arr1 (check) --> 逐一 copy
: cpy3 : 938 arr2=arr1 (check) --> 4 bytes 處理
: cpy4 : 531 arr2=arr1 (check) --> struct 256 bytes 處理
: cpy5 : 500 arr2=arr1 (check) --> struct 1024 + 256 + 4 bytes 處理。
: vc 開 option 測時會很不準,懶得再用 gcc 測 (其實也懶得再看 .asm)
: 其實上面的 cpy4 / cpy5 還是有可改善空間,希望這些意見能給你一些幫助。
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 180.176.120.10
→
03/19 02:19, , 1F
03/19 02:19, 1F
→
03/19 02:28, , 2F
03/19 02:28, 2F
→
03/19 02:28, , 3F
03/19 02:28, 3F
→
03/19 02:29, , 4F
03/19 02:29, 4F
推
03/19 02:30, , 5F
03/19 02:30, 5F
→
03/19 02:32, , 6F
03/19 02:32, 6F
→
03/19 02:32, , 7F
03/19 02:32, 7F
※ 編輯: WeBurn 來自: 180.176.120.10 (03/19 03:45)
推
03/19 03:46, , 8F
03/19 03:46, 8F
※ 編輯: WeBurn 來自: 180.176.120.10 (03/19 04:12)
→
03/19 04:12, , 9F
03/19 04:12, 9F
→
03/19 04:25, , 10F
03/19 04:25, 10F
→
03/19 04:26, , 11F
03/19 04:26, 11F
→
03/19 04:26, , 12F
03/19 04:26, 12F
推
03/19 07:27, , 13F
03/19 07:27, 13F
推
03/19 07:59, , 14F
03/19 07:59, 14F
→
03/19 08:50, , 15F
03/19 08:50, 15F
→
03/19 09:52, , 16F
03/19 09:52, 16F
→
03/19 09:52, , 17F
03/19 09:52, 17F
→
03/19 09:53, , 18F
03/19 09:53, 18F
推
03/19 09:55, , 19F
03/19 09:55, 19F
→
03/19 11:30, , 20F
03/19 11:30, 20F
→
03/19 11:30, , 21F
03/19 11:30, 21F
→
03/19 11:33, , 22F
03/19 11:33, 22F
→
03/19 11:33, , 23F
03/19 11:33, 23F
→
03/19 11:34, , 24F
03/19 11:34, 24F
推
03/19 11:41, , 25F
03/19 11:41, 25F
→
03/19 11:42, , 26F
03/19 11:42, 26F
→
03/19 11:42, , 27F
03/19 11:42, 27F
推
03/21 17:42, , 28F
03/21 17:42, 28F
→
03/21 17:42, , 29F
03/21 17:42, 29F
推
03/22 00:31, , 30F
03/22 00:31, 30F
→
03/22 00:32, , 31F
03/22 00:32, 31F
→
03/22 00:32, , 32F
03/22 00:32, 32F
→
03/22 03:14, , 33F
03/22 03:14, 33F
→
03/22 03:15, , 34F
03/22 03:15, 34F
→
03/22 03:16, , 35F
03/22 03:16, 35F
→
03/22 03:16, , 36F
03/22 03:16, 36F
→
03/22 03:33, , 37F
03/22 03:33, 37F
→
03/22 03:33, , 38F
03/22 03:33, 38F
推
03/22 14:58, , 39F
03/22 14:58, 39F
推
03/22 23:23, , 40F
03/22 23:23, 40F
→
03/22 23:23, , 41F
03/22 23:23, 41F
→
03/22 23:24, , 42F
03/22 23:24, 42F
→
03/22 23:25, , 43F
03/22 23:25, 43F
→
03/22 23:26, , 44F
03/22 23:26, 44F
→
03/22 23:27, , 45F
03/22 23:27, 45F
→
03/22 23:28, , 46F
03/22 23:28, 46F
→
03/22 23:29, , 47F
03/22 23:29, 47F
→
03/22 23:30, , 48F
03/22 23:30, 48F
→
03/23 04:04, , 49F
03/23 04:04, 49F
→
03/23 04:05, , 50F
03/23 04:05, 50F
討論串 (同標題文章)