user-0 提问: memset和循环置位哪个花时间啊？

回复:
user: user-1
content: 使用电脑计时有时误差会很大，因为待测程序段的运行会影响电脑时钟。 将待测程序段循环足够多次，手动掐秒表计时可能更准确。

user: user-1
content: 无Profiler不谈效率。

user: user-2
content: memset是优化过的，从老赵贴的代码中可以看出它是这样优化的（当然这是针对特定的平台的优化）： 对于特殊的case（内存置0且buffer长度超过0x80），调用SSE2指令； 其它case，则是以dword为单位而不是byte为单位置内存，这就减少了memset中循环的次数。  至于 for (i = 0; i < N; i++) a[i] = 0; 有没有优化呢？就我个人知道的，这种简单的for循环，在多核的机器下，如果编译器做得好（很多前提条件，是吧） 是可以生成代码，使其能在多核上运行，大概是这个意思： for (i = 0; i < N/4; i++) a[i] = 0; // run on core1 for (i = N/4; i < N/2; i++) a[i] = 0; // run on core2 for (i = N/2; i < N*3/4; i++) a[i] = 0; // ... for (i = N*3/4; i < N; i++) a[i] = 0;  说这么多，想表达什么呢？ 1）先功能，后性能；  2）一句简单的“哪个花时间”，缺少条件的情况下，这问题没有任何意义； 如果一定要比较“哪个花时间”，那么请在你关心的上下文（你手头的机器，或者最终要跑的机器），反复多次运行并测量（不是运行一次并测量，这样误差太大），即 start = now(); 运行一万次（给数组置0） end = now(); 如果一万次的结果还不明显，比如只差一两秒，这样说明不了问题，请加大一万这个数目，并反复这个实验。 注意：机器不要跑其他的程序／服务⋯⋯，即尽量减少干扰  3）优化无处不在，但是都是针对特定的环境／平台，所以这就是为什么先性能，后功能的原因。

user: user-3
content: void *memset(void *s, int c, size_t count) 579 { 580         char *xs = s; 581  582         while (count--) 583                 *xs++ = c; 584         return s; 585 }  上层库也是用的循环搞定的。由于存在调用开销，有可能比直接用for循环要一丁点慢！ 如果是下面这个版本  static inline void *__memset_generic(void *s, char c, size_t count) 208 { 209         int d0, d1; 210         asm volatile("rep\n\t" 211                      "stosb" 212                      : "=&c" (d0), "=&D" (d1) 213                      : "a" (c), "1" (s), "" (count) 214                      : "memory"); 215         return s; 216 }  这个比较猛，这是linux内核中的代码，经个人测试很显然比for和memset API都要高效一些

user: user-4
content: 我相信很难写出比memset更快的算法

user: user-5
content: 数据量很少的话，用for多了用memset

user: user-6
content: 可以把int换成char，看下时间，就知道效果了，自己写的for和memset的差距了（一般的memset都是4char的）  可以这么改一下，看看效率，这里的4就是4int版本的处理 for(i = 0;i < N; i+=4 ) {moreSum[i] = 0;moreSum[i+1] = 0;moreSum[i+2] = 0;moreSum[i+3] = 0;} for(;i < N; i++ ) moreSum[i] = 0;

user: user-7
content: 不用讲,自然是memset效率高 汇编有一条指令是内存传送的 可以一次传送N个字节 你的程序也要翻译成汇编的 你自己看着办

user: user-0
content: 引用 3 楼 majia2011 的回复:晕，刚回复完，lz就改了代码  第二个for竟然删除了 我自己失误了。再给我看看我2楼的回复。

user: user-0
content: 引用 1 楼 majia2011 的回复:开玩笑吧，你  1是写了，n个int 2是写了，n个int[n]  你自己说哪个效率高  我改了下代码，再给我看看。多谢。

user: user-8
content: 尽可能用memset  引用 楼主 middilestep 的回复:把一个数组置零， memset和循环置位哪个花时间啊？    #include <stdio.h>  #include <windows.h>  #define N 65535 int moreSum[N];  int main() { 	int i = 0; 	SYSTEMTIME sys; 	GetLocalTime(&sys); 	//printf("%4d/%02d/%02d %02d:%02d:%02d.%03d weekday:%1d\n",sys.wYear,sys.wMonth,sys.wDay,sys.wHour,sys.wMinute,sys.wSecond,sys.wMilliseconds,sys.wDayOfWeek); 	printf("#0 %02dm.%03dms\n",sys.wSecond,sys.wMilliseconds);  	for(i = 0;i < N; i++ ) moreSum[i] = 0; 	GetLocalTime(&sys); 	printf("#1 %02dm.%03dms\n",sys.wSecond,sys.wMilliseconds);  	 memset(moreSum,0,sizeof(moreSum)); 	GetLocalTime(&sys); 	printf("#2 %02dm.%03dms\n",sys.wSecond,sys.wMilliseconds);  	return 0; }      #0 00m.218ms #1 00m.218ms #2 00m.218ms

user: user-6
content: 晕，刚回复完，lz就改了代码  第二个for竟然删除了

user: user-0
content: #define N 65535*10  #0 04m.118ms #1 04m.123ms #2 04m.123ms  ms 看出点来了

user: user-6
content: 开玩笑吧，你  1是写了，n个int 2是写了，n个int[n]  你自己说哪个效率高

user: user-3
content: 引用 12 楼 zhao4zhong1 的回复:千万别盲目崇拜linux： 先 http://www.microsoft.com/visualstudio/chs/downloads#d-2010-express 点开Visual C++ 2010 Express下面的语言选‘简体中文’，再点立即安装  再参考C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\intel\memset.asm         page    ,132         title   memset - set sections of memory all to one byte ;*** ;memset.asm - set a section of memory to all one byte ; ;       Copyright (c) Microsoft Corporation. All rights reserved. ; ;Purpose: ;       contains the memset() routine ; ;*******************************************************************************          .xlist         include cruntime.inc         .list  page ;*** ;char *memset(dst, value, count) - sets "count" bytes at "dst" to "value" ; ;Purpose: ;       Sets the first "count" bytes of the memory starting ;       at "dst" to the character value "value". ; ;       Algorithm: ;       char * ;       memset (dst, value, count) ;               char *dst; ;               char value; ;               unsigned int count; ;               { ;               char *start = dst; ; ;               while (count--) ;                       *dst++ = value; ;               return(start); ;               } ; ;Entry: ;       char *dst - pointer to memory to fill with value ;       char value - value to put in dst bytes ;       int count - number of bytes of dst to fill ; ;Exit: ;       returns dst, with filled bytes ; ;Uses: ; ;Exceptions: ; ;*******************************************************************************          CODESEG      extrn   _VEC_memzero:near     extrn   __sse2_available:dword          public  memset memset proc \         dst:ptr byte, \         value:byte, \         count:dword          OPTION PROLOGUE:NONE, EPILOGUE:NONE          .FPO    ( 0, 3, 0, 0, 0, 0 )          mov     edx,[esp + 0ch] ; edx = "count"         mov     ecx,[esp + 4]   ; ecx points to "dst"          test    edx,edx         ; 0?         jz      short toend     ; if so, nothing to do          xor     eax,eax         mov     al,[esp + 8]    ; the byte "value" to be stored  ; Special case large block zeroing using SSE2 support     test    al,al ; memset using zero initializer?     jne     dword_align     cmp     edx,080h ; block size exceeds size threshold?     jb      dword_align     cmp     DWORD PTR __sse2_available,0 ; SSE2 supported?     je      dword_align      jmp     _VEC_memzero ; use fast zero SSE2 implementation     ; no return  ; Align address on dword boundary dword_align:          push    edi             ; preserve edi         mov     edi,ecx         ; edi = dest pointer          cmp     edx,4           ; if it's less then 4 bytes         jb      tail            ; tail needs edi and edx to be initialized          neg     ecx         and     ecx,3           ; ecx = # bytes before dword boundary         jz      short dwords    ; jump if address already aligned          sub     edx,ecx         ; edx = adjusted count (for later) adjust_loop:         mov     [edi],al         add     edi,1         sub     ecx,1         jnz     adjust_loop  dwords: ; set all 4 bytes of eax to [value]         mov     ecx,eax         ; ecx=0/0/0/value         shl     eax,8           ; eax=0/0/value/0          add     eax,ecx         ; eax=0/0val/val          mov     ecx,eax         ; ecx=0/0/val/val          shl     eax,10h         ; eax=val/val/0/0          add     eax,ecx         ; eax = all 4 bytes = [value]  ; Set dword-sized blocks         mov     ecx,edx         ; move original count to ecx         and     edx,3           ; prepare in edx byte count (for tail loop)         shr     ecx,2           ; adjust ecx to be dword count         jz      tail            ; jump if it was less then 4 bytes          rep     stosd main_loop_tail:         test    edx,edx         ; if there is no tail bytes,         jz      finish          ; we finish, and it's time to leave ; Set remaining bytes  tail:         mov     [edi],al        ; set remaining bytes         add     edi,1          sub     edx,1           ; if there is some more bytes         jnz     tail            ; continue to fill them  ; Done finish:         mov     eax,[esp + 8]   ; return dest pointer         pop     edi             ; restore edi          ret  toend:         mov     eax,[esp + 4]   ; return dest pointer          ret  memset  endp          end  崇拜？大婶真会开玩笑！迫于环境的问题，没有涉及windows相关资料。只是在linux下比较linux的几个接口性能差别！没有对对大婶的windows做任何妄言！

user: user-1
content: 千万别盲目崇拜linux： 先 http://www.microsoft.com/visualstudio/chs/downloads#d-2010-express 点开Visual C++ 2010 Express下面的语言选‘简体中文’，再点立即安装  再参考C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\intel\memset.asm         page    ,132         title   memset - set sections of memory all to one byte ;*** ;memset.asm - set a section of memory to all one byte ; ;       Copyright (c) Microsoft Corporation. All rights reserved. ; ;Purpose: ;       contains the memset() routine ; ;*******************************************************************************          .xlist         include cruntime.inc         .list  page ;*** ;char *memset(dst, value, count) - sets "count" bytes at "dst" to "value" ; ;Purpose: ;       Sets the first "count" bytes of the memory starting ;       at "dst" to the character value "value". ; ;       Algorithm: ;       char * ;       memset (dst, value, count) ;               char *dst; ;               char value; ;               unsigned int count; ;               { ;               char *start = dst; ; ;               while (count--) ;                       *dst++ = value; ;               return(start); ;               } ; ;Entry: ;       char *dst - pointer to memory to fill with value ;       char value - value to put in dst bytes ;       int count - number of bytes of dst to fill ; ;Exit: ;       returns dst, with filled bytes ; ;Uses: ; ;Exceptions: ; ;*******************************************************************************          CODESEG      extrn   _VEC_memzero:near     extrn   __sse2_available:dword          public  memset memset proc \         dst:ptr byte, \         value:byte, \         count:dword          OPTION PROLOGUE:NONE, EPILOGUE:NONE          .FPO    ( 0, 3, 0, 0, 0, 0 )          mov     edx,[esp + 0ch] ; edx = "count"         mov     ecx,[esp + 4]   ; ecx points to "dst"          test    edx,edx         ; 0?         jz      short toend     ; if so, nothing to do          xor     eax,eax         mov     al,[esp + 8]    ; the byte "value" to be stored  ; Special case large block zeroing using SSE2 support     test    al,al ; memset using zero initializer?     jne     dword_align     cmp     edx,080h ; block size exceeds size threshold?     jb      dword_align     cmp     DWORD PTR __sse2_available,0 ; SSE2 supported?     je      dword_align      jmp     _VEC_memzero ; use fast zero SSE2 implementation     ; no return  ; Align address on dword boundary dword_align:          push    edi             ; preserve edi         mov     edi,ecx         ; edi = dest pointer          cmp     edx,4           ; if it's less then 4 bytes         jb      tail            ; tail needs edi and edx to be initialized          neg     ecx         and     ecx,3           ; ecx = # bytes before dword boundary         jz      short dwords    ; jump if address already aligned          sub     edx,ecx         ; edx = adjusted count (for later) adjust_loop:         mov     [edi],al         add     edi,1         sub     ecx,1         jnz     adjust_loop  dwords: ; set all 4 bytes of eax to [value]         mov     ecx,eax         ; ecx=0/0/0/value         shl     eax,8           ; eax=0/0/value/0          add     eax,ecx         ; eax=0/0val/val          mov     ecx,eax         ; ecx=0/0/val/val          shl     eax,10h         ; eax=val/val/0/0          add     eax,ecx         ; eax = all 4 bytes = [value]  ; Set dword-sized blocks         mov     ecx,edx         ; move original count to ecx         and     edx,3           ; prepare in edx byte count (for tail loop)         shr     ecx,2           ; adjust ecx to be dword count         jz      tail            ; jump if it was less then 4 bytes          rep     stosd main_loop_tail:         test    edx,edx         ; if there is no tail bytes,         jz      finish          ; we finish, and it's time to leave ; Set remaining bytes  tail:         mov     [edi],al        ; set remaining bytes         add     edi,1          sub     edx,1           ; if there is some more bytes         jnz     tail            ; continue to fill them  ; Done finish:         mov     eax,[esp + 8]   ; return dest pointer         pop     edi             ; restore edi          ret  toend:         mov     eax,[esp + 4]   ; return dest pointer          ret  memset  endp          end