C 在什么情况下,库函数的效率不值得调用它们的开销呢?

C 在什么情况下,库函数的效率不值得调用它们的开销呢?,c,performance,memcpy,C,Performance,Memcpy,如果要复制1000个字节,显然memcpy()是更好的选择。显然,如果要复制一个字节,只需将其赋值是更好的选择Array[0]=“A”。这memcpy(数组,(constchar[]){'A'},1)是愚蠢的。也可能是这个memcpy(数组,(constchar[]){'B'},2),因为调用函数的开销比逐个分配两个字节浪费更多的性能。但是我应该在什么时候使用memcpy?最大字节数是多少?最好一次内联复制一个字节?假设编译器不会自动内联memcpy调用,因为有些编译器不会。与直接分配字节相比,

如果要复制1000个字节,显然
memcpy()
是更好的选择。显然,如果要复制一个字节,只需将其赋值是更好的选择
Array[0]=“A”。这
memcpy(数组,(constchar[]){'A'},1)是愚蠢的。也可能是这个
memcpy(数组,(constchar[]){'B'},2),因为调用函数的开销比逐个分配两个字节浪费更多的性能。但是我应该在什么时候使用
memcpy
?最大字节数是多少?最好一次内联复制一个字节?假设编译器不会自动内联
memcpy
调用,因为有些编译器不会。与直接分配字节相比,我什么时候应该
memcpy

但是我应该在什么时候使用
memcpy
?最大字节数是多少?最好一次内联复制一个字节

如果不分析代码,就不可能说。在准确了解以下情况之前,不要对此类精细优化进行假设:

  • 编译器和编译器版本
  • 编译标志和优化标志
  • 由编译器生成的代码
  • 使用函数的上下文
  • 您为之编译的机器
最重要的是,根本不要假设代码将如何编译,只需编译并查看即可。如果您想知道在这种细粒度级别上什么是最好的:应用相关标志、编译、查看生成代码的程序集、对其进行基准测试,然后问自己一些问题,如“如何更有效地编译此代码?”、“为了生成不同的/更快的代码,我可以做些什么?”,“我应该自己写得更好吗?”

在godbolt中,程序集说
调用memcpy
,即使它应该内联

同样,如果不知道确切的代码、编译器和编译标志,这也没有多大意义。当可以明显优化以加快速度时,任何好的编译器都不会留下
调用memcpy
。您可以在中看到它

gcc x.c gcc-O3 x.c
mov edx、128 movdqu xmm0、XMMWORD PTR[rsp]
移动rsi,移动rcx移动QU xmm1,XMMWORD PTR[rsp+16]
mov rdi,rax lea rdi,[rsp+1024]
调用memcpy movdqu xmm2,XMMWORD PTR[rsp+32]
movdqu xmm3,XMMWORD PTR[rsp+48]
movdqu xmm4,XMMWORD PTR[rsp+64]
movdqu xmm5,XMMWORD PTR[rsp+80]
movups XMMWORD PTR[rsp+1024],xmm0
movdqu xmm6,XMMWORD PTR[rsp+96]
movdqu xmm7,XMMWORD PTR[rsp+112]
movups XMMWORD PTR[rsp+1040],xmm1
movups XMMWORD PTR[rsp+1056],xmm2
movups XMMWORD PTR[rsp+1072],xmm3
movups XMMWORD PTR[rsp+1088],xmm4
movups XMMWORD PTR[rsp+1104],xmm5
movups XMMWORD PTR[rsp+1120],xmm6
movups XMMWORD PTR[rsp+1136],xmm7

您对性能做出了一些错误的假设:

显然,如果要复制一个字节,只分配它是更好的选择
Array[0]='A';
。这个
memcpy(Array,(const char[]){'A'},1);
很愚蠢

出于可读性原因,赋值更好。但从性能角度来看,在任何启用优化的体面编译器上,赋值实际上都是相同的:

#include <string.h>

void test1(char* Array)
{
    Array[0] = 'A';
}

void test2(char* Array)
{
    memcpy(Array, (const char[]){'A'}, 1);
}
test1:
        mov     BYTE PTR [rdi], 65
        ret
test2:
        mov     BYTE PTR [rdi], 65
        ret

您所做的就是所谓的过早优化。优化是一个复杂的主题,可以通过经验和分析来解决。因此,首先要编写可读性的代码。然后,如果存在性能问题,不要在黑暗中根据您认为的问题进行优化;首先分析根据评测结果进行优化。

始终
memcpy()
,担心更多相关的事情。标准答案是“评测代码”,编译器可以内联调用memcpy()。你可以相信它几乎每一次都比你做得更好。@user13783520这当然是真的,但没有以前为嵌入式系统开发时那么多,因为如果你开发的是有缺陷的商业编译器,几乎没有什么完整性。哪个编译器,哪些选项?我刚刚试过用-O3和编译器比
memcpy()省去了很多
用于简单的示例。现代
clang
gcc
也可以在编译时已知数据的情况下优化内存分配。假设我只使用gcc和Linux。@user13783520信息不够。如果你想要一个明确的答案,你必须至少提供我上面所说的一切。仅““GCC和Linux”还不够,我只能建议您1)使用优化,2)查看生成的代码,3)分析它。