我正在调试一个性能敏感的事务处理系统。
我找到了一个使用__builtin_memcpy和__builtin_memset而不是memcpy和memset的代码。
什么是__builtin_functions? ,以防止架构或编译器的依赖问题?
或..是否有任何性能原因,首选__builtin_functions?
谢谢你:D答案 0 :(得分:5)
传统的库函数,标准memcpy
只是对函数的调用。不幸的是,memcpy
通常被称为每个小副本,并且调用函数,改组几个字节并返回的开销是相当多的开销(特别是因为memcpy
在开头添加了额外的东西。处理未对齐内存,展开循环等的函数,以便在LARGE副本上做得很好。)
因此,对于编译器来优化它们,它需要“知道”如何做例如memcpy
- 这个解决方案是在编译器中“内置”一个函数,然后包含这样的代码这样:
int generate_builtin_memcpy(expr arg1, expr arg2, expr size)
{
if (is_constant(size) && eval(size) < SOME_NUMBER)
{
... do magic inline memory copy ...
}
else
{
... call "real" memcpy ...
}
}
[对于可重定向编译器,每个CPU架构通常都有这些函数中的一个,它们在调用“真实”memcpy
的条件或使用内联memcpy时具有不同的配置。] < / p>
这里的关键是你实际上可以编写自己的memcpy
函数,它不是基于__builtin_memcpy()
,它总是一个函数,并且与普通函数不同。 {1}} [如果你改变它的行为会有很多麻烦,因为C标准库可能会在几千个地方调用memcpy
- 但是例如在{{{}进行统计。调用1}},副本的大小可以是一个这样的用例]。
使用memcpy
的另一个重要原因是它们提供的代码本来必须用内联汇编程序编写,或者根本不可用于程序员。设置/获取特殊寄存器就是这样的事情。
还有其他技术可以解决这个问题,例如memcpy
有一个__builtin_*
,它假定库调用与其他替代方法执行常见功能,例如,因为clang
更重“ “比LibraryPass
,它将合适的printf
替换为puts
,并且当使用常量等调用时,许多三角函数和其他数学函数被解析为常见的简单值。
直接为printf("constant string with no formatting\n")
或puts("constant string with no formatting")
或其他类似函数调用__builtin_*
可能是错误的做法 - 它只会使您的代码不那么便携,而且根本不会更快。在没有其他情况下调用memcpy
通常是在某些棘手情况下的解决方案 - 但您应该将其包装在您自己的函数中,例如
sin
这样,当您移植到Windows时,您可以轻松地执行:
__builtin_special_function
答案 1 :(得分:2)
__builtin_*
函数是编译器库提供的优化函数。这些可能是标准库函数的内置版本,例如memcpy,也许更典型的是一些数学函数。
或者,它们可能是针对特定目标的典型任务的高度优化功能 - 例如,DSP可能具有内置FFT功能
作为__builtin_
提供的函数由编译器的开发人员确定,并将记录在编译器的手册中。
不同的CPU类型和编译器是针对不同的用例而设计的,这将反映在所提供的内置函数范围内。
内置函数可能会利用目标处理器中的专用指令,或者可能通过使用查找表而不是直接计算值或任何其他合理的优化来折衷速度精度,所有这些都应记录在案。
这些肯定是而不是来减少对特定编译器或cpu的依赖,实际上恰恰相反。它实际上添加了一个依赖项,因此这些可能会包含在预处理器检查中,例如
#ifdef SOME_CPU_FLAG
#define MEMCPY __builtin_memcpy
#else
#define MEMCPY memcpy
答案 2 :(得分:1)
在编译器上,__ builtin_memcpy可以回退到发射 一个memcpy函数调用。也不太能干 通过选择慢速路径,编译器简化的能力 无条件地发出记忆电话。