清除一个小整数数组:memset与for循环

有两种方法可以将整数/浮点数组清零:

memset(array, 0, sizeof(int)*arraysize); 

要么:

 for (int i=0; i <arraysize; ++i) array[i]=0; 

显然,对于大型arraysize ,memset更快。 但是,memset的开销实际上大于for循环的开销? 例如,对于大小为5的数组 – 这将是最好的? 第一个,第二个,或者甚至是未滚动的版本:

 array[0] = 0; array[1] = 0; array[2] = 0; array[3] = 0; array[4] = 0; 

很有可能,memset()会被你的编译器内联(大多数编译器把它看作是一个“内在的”,基本上意味着内联,除非是在最低优化或明确禁止的情况下)。

例如,下面是GCC 4.3的一些发行说明 :

块移动( memcpy )和块集( memset )的代码生成被重写。 GCC现在可以根据正在复制的块的大小以及正在优化的CPU来select最佳algorithm(循环,展开循环,带有rep前缀的指令或库调用)。 添加了一个新的选项-minline-stringops-dynamically 。 使用这个选项,string操作的未知大小被扩展,使得小块被内嵌代码复制,而大块则使用库调用。 当库实现能够使用caching层次结构提示时,这会比-minline-all-stringops产生更快的代码。 select特定algorithm的启发式可以通过-mstringop-strategy来覆盖。 最近还内联了不同于0值的memset

编译器可能可以用你给出的替代例子做类似的事情,但我敢打赌,这是不太可能的。

一眼就能看出它的意图是什么,而且更加直观明了(不是说这个循环特别困难)。

正如迈克尔已经指出的那样,gcc和我认为大多数其他编译器已经很好地优化了这一点。 例如,海湾合作委员会这样做

 char arr[5]; memset(arr, 0, sizeof arr); 

 movl $0x0, <arr+0x0> movb $0x0, <arr+0x4> 

没有比这更好的了…

没有测量就没有办法回答这个问题。 它将完全取决于编译器,CPU和运行时库的实现。

memset()可以是一个“代码异味”的位,因为它可能容易发生缓冲区溢出,参数反转,并且具有只能清除“字节方式”的不幸的能力。 然而,可以肯定的是,除极端情况外,这将是“最快”的。

我倾向于使用macros来包装,以避免一些问题:

 #define CLEAR(s) memset(&(s), 0, sizeof(s)) 

这避开了尺寸计算,并消除了交换长度和参数的问题。

总之,使用memset()“引擎盖下”。 写下你的意图,让编译器担心优化。 大多数人都非常擅长。

考虑到这个代码本身已经被告知。 但是,如果你把它看作是一个我什么都不知道的程序,那么还有其他的东西可以做。 例如,如果要每隔一段时间执行一次这段代码来清除一个数组,你可以运行一个线程,它不断地分配一个新的数组元素赋值给一个全局variables,当你的代码需要清除数组的时候,只是指向。

这是第三种select。 当然如果你打算在至less有两个内核的处理器上运行你的代码,这是有道理的。 此外,代码必须运行多次才能看到好处。 只有一次运行,你可以声明一个填充零的数组,然后在需要的时候指向它。

希望这可以帮助某人