Cla*_*diu 56 c performance benchmarking
有两种方法可以将整数/浮点数组清零:
memset(array, 0, sizeof(int)*arraysize);
Run Code Online (Sandbox Code Playgroud)
要么:
for (int i=0; i <arraysize; ++i)
array[i]=0;
Run Code Online (Sandbox Code Playgroud)
显然,memset对于大型更快arraysize
.但是,在什么时候memset的开销实际上大于for循环的开销?例如,对于大小为5的数组 - 哪个最好?第一个,第二个,甚至可能是未滚动的版本:
array[0] = 0;
array[1] = 0;
array[2] = 0;
array[3] = 0;
array[4] = 0;
Run Code Online (Sandbox Code Playgroud)
Mic*_*urr 45
很可能,memset()将由编译器内联(大多数编译器将其视为'内在',这基本上意味着它是内联的,除非可能是最低优化或除非明确禁用).
重写了块移动(
memcpy
)和块集(memset
)的代码生成.GCC现在可以根据要复制的块的大小和优化的CPU来选择最佳算法(循环,展开循环,带有rep前缀的指令或库调用).-minline-stringops-dynamically
添加了一个新选项 .使用此选项,将扩展未知大小的字符串操作,以便通过内联代码复制小块,而对于大块,则使用库调用.-minline-all-stringops
与库实现能够使用缓存层次结构提示相比,这会产生更快的代码 .选择特定算法的启发式算法可以通过覆盖-mstringop-strategy
.最新memset
的不同于0的值也 被内联.
编译器可能会使用您提供的替代示例执行类似操作,但我敢打赌它不太可能.
而且grep
一眼就能看出启动的目的是什么,而且更直接明显(不是循环特别难以理解).
小智 21
正如迈克尔已经指出的那样,gcc和我猜大多数其他编译器已经非常好地优化了它.例如gcc就是这样
char arr[5];
memset(arr, 0, sizeof arr);
Run Code Online (Sandbox Code Playgroud)
成
movl $0x0, <arr+0x0>
movb $0x0, <arr+0x4>
Run Code Online (Sandbox Code Playgroud)
它没有比那更好......
没有测量就无法回答这个问题.它完全取决于编译器,cpu和运行时库实现.
memset()可能是一个"代码味道",因为它可能容易出现缓冲区溢出,参数反转,并且具有仅清除"逐字节"的不幸能力.然而,可以肯定的是,除了极端情况外,它将"最快".
我倾向于使用宏来包装它以避免一些问题:
#define CLEAR(s) memset(&(s), 0, sizeof(s))
Run Code Online (Sandbox Code Playgroud)
这避免了尺寸计算,并消除了交换长度和值的参数问题.
简而言之,使用memset()"引擎盖下".写下你想要的东西,让编译器担心优化.大多数人都非常擅长.