在C中使用memset()有什么好处

2023-11-24

我很好奇在类似于下面的情况下使用 memset() 在效率方面是否有任何优势。

鉴于以下缓冲区声明...

struct More_Buffer_Info
{
    unsigned char a[10];
    unsigned char b[10];
    unsigned char c[10];
};

struct My_Buffer_Type
{
    struct More_Buffer_Info buffer_info[100];
};

struct My_Buffer_Type my_buffer[5];

unsigned char *p;
p = (unsigned char *)my_buffer;

除了代码行数较少之外,使用它还有一个优点:

memset((void *)p, 0, sizeof(my_buffer));

对此:

for (i = 0; i < sizeof(my_buffer); i++)
{
    *p++ = 0;
}

这适用于两者memset() and memcpy():

  1. 更少的代码:正如您已经提到的,它更短,代码行更少。
  2. 更具可读性:较短通常也使其更具可读性。 (memset()比那个循环更具可读性)
  3. 它可以更快:有时它可以允许更积极的编译器优化。 (所以可能会更快)
  4. 错位:在某些情况下,当您在不支持未对齐访问的处理器上处理未对齐的数据时,memset() and memcpy()可能是唯一干净的解决方案。

对第3点进行扩展,memset()编译器可以使用 SIMD 等进行大量优化。如果您编写一个循环,则编译器首先需要“弄清楚”它的作用,然后才能尝试优化它。

这里的基本思想是memset()和类似的库函数,在某种意义上,“告诉”编译器你的意图。


正如 @Oli 在评论中提到的,有一些缺点。我将在这里扩展它们:

  1. 你需要确保memset()实际上做你想做的事。该标准并未规定各种数据类型的零在内存中必然为零。
  2. 对于非零数据,memset()仅限于 1 字节内容。所以你不能使用memset()如果你想设置一个数组ints 为零以外的值(或0x01010101或者其他的东西...)。
  3. 尽管很少见,但在某些极端情况下,实际上可以使用自己的循环在性能上击败编译器。*

*我将根据我的经验举一个例子:

虽然memset() and memcpy()通常是经过编译器特殊处理的编译器内在函数,它们仍然是generic功能。他们没有提及数据类型,包括数据的对齐方式。

因此,在少数(尽管罕见)情况下,编译器无法确定内存区域的对齐方式,因此必须生成额外的代码来处理未对齐情况。然而,如果您是程序员,100% 确定对齐,那么使用循环实际上可能会更快。

一个常见的例子是使用 SSE/AVX 内在函数。 (例如复制一个 16/32 字节对齐的数组floats) 如果编译器无法确定 16/32 字节对齐,则需要使用未对齐的加载/存储和/或处理代码。如果您只是使用 SSE/AVX 对齐的加载/存储内在函数编写一个循环,您可以probably做得更好。

float *ptrA = ...  //  some unknown source, guaranteed to be 32-byte aligned
float *ptrB = ...  //  some unknown source, guaranteed to be 32-byte aligned
int length = ...   //  some unknown source, guaranteed to be multiple of 8

//  memcopy() - Compiler can't read comments. It doesn't know the data is 32-byte
//  aligned. So it may generate unnecessary misalignment handling code.
memcpy(ptrA, ptrB, length * sizeof(float));

//  This loop could potentially be faster because it "uses" the fact that
//  the pointers are aligned. The compiler can also further optimize this.
for (int c = 0; c < length; c += 8){
    _mm256_store_ps(ptrA + c, _mm256_load_ps(ptrB + c));
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在C中使用memset()有什么好处 的相关文章

随机推荐