__builtin__functions 在 C++ 中的作用是什么?
What are __builtin__functions for in C++?
我正在调试一个对性能敏感的事务处理系统。
我找到了一个使用 __builtin_memcpy 和 __builtin_memset 而不是 memcpy 和 memset 的代码。
__builtin_functions 有什么用?
, 以防止对体系结构或编译器的依赖性问题?
或者.. 是否有任何性能原因首选 __builtin_functions?
谢谢你:D
在编译器说明中,__builtin_memcpy 可以回退到发射
memcpy 函数调用。能力也较差
编译器通过选择慢路径来简化的能力
无条件发出 memcpy 调用。
__builtin_*
函数是编译器库提供的优化函数。这些可能是标准库函数的内置版本,例如 memcpy,也许更典型的是一些数学函数。
或者,它们可能是针对特定目标的典型任务的高度优化函数 - 例如 DSP 可能具有内置 FFT 函数
提供哪些函数作为__builtin_
由编译器的开发人员决定,并将记录在编译器的手册中。
不同的 CPU 类型和编译器是为不同的用例设计的,这将反映在提供的内置函数的范围内。
内置函数可能会使用目标处理器中的专用指令,或者可能会通过使用查找表而不是直接计算值或任何其他合理的优化来牺牲准确性以换取速度,所有这些都应记录在案。
这些绝对不是减少对特定编译器或cpu的依赖,事实上恰恰相反。它实际上添加了一个依赖项,因此这些可能包含在预处理器检查中,例如
#ifdef SOME_CPU_FLAG
#define MEMCPY __builtin_memcpy
#else
#define MEMCPY memcpy
传统的库函数,标准的memcpy
只是一个函数的调用。不幸的是,memcpy
经常被每个小副本调用,调用函数、洗牌几个字节和返回的开销是相当大的开销(特别是因为 memcpy
在处理未对齐内存、展开循环等的功能,以便在大型副本上表现出色)。
因此,为了让编译器优化这些,它需要 "know" 如何做,例如 memcpy
- 解决方案是在编译器中加入一个函数 "builtin" ,然后包含如下代码:
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 体系结构通常都有这些函数之一,对于调用 "real" memcpy
的条件或何时调用具有不同的配置使用内联 memcpy。]
这里的关键是您实际上可以编写自己的 memcpy
函数,它不是基于 __builtin_memcpy()
,它始终是一个函数,并且与正常 memcpy
[如果你改变它的行为很多你会有点麻烦,因为 C 标准库可能在几千个地方调用 memcpy
- 但是例如统计多少次memcpy
被调用,副本的大小可能就是这样一个用例]。
使用 __builtin_*
的另一个重要原因是它们提供的代码否则必须用内联汇编程序编写,或者可能根本不提供给程序员。 Setting/getting 特殊寄存器就是这样的东西。
还有其他技术可以解决这个问题,例如 clang
有一个 LibraryPass
假设库调用与其他替代方法具有共同的功能,例如因为 printf
很多"heavier" 比 puts
,它把合适的 printf("constant string with no formatting\n")
替换成 puts("constant string with no formatting")
,许多三角函数和其他数学函数在用常量调用时被解析为常见的简单值等
直接为 memcpy
或 sin
之类的函数调用 __builtin_*
可能是错误的做法 - 它只会降低代码的可移植性并且根本不确定更快。在没有其他情况下调用 __builtin_special_function
通常是某些棘手情况下的解决方案 - 但您可能应该将其包装在您自己的函数中,例如
int get_magic_property()
{
return __builtin_get_magic_property();
}
这样,当您移植到 Windows 时,您可以轻松地做到:
int get_magic_property()
{
#if WIN32
return Win32GetMagicPropertyEx();
#else
return __builtin_magic_property();
#endif
}
我正在调试一个对性能敏感的事务处理系统。
我找到了一个使用 __builtin_memcpy 和 __builtin_memset 而不是 memcpy 和 memset 的代码。
__builtin_functions 有什么用? , 以防止对体系结构或编译器的依赖性问题?
或者.. 是否有任何性能原因首选 __builtin_functions?
谢谢你:D
在编译器说明中,__builtin_memcpy 可以回退到发射 memcpy 函数调用。能力也较差 编译器通过选择慢路径来简化的能力 无条件发出 memcpy 调用。
__builtin_*
函数是编译器库提供的优化函数。这些可能是标准库函数的内置版本,例如 memcpy,也许更典型的是一些数学函数。
或者,它们可能是针对特定目标的典型任务的高度优化函数 - 例如 DSP 可能具有内置 FFT 函数
提供哪些函数作为__builtin_
由编译器的开发人员决定,并将记录在编译器的手册中。
不同的 CPU 类型和编译器是为不同的用例设计的,这将反映在提供的内置函数的范围内。
内置函数可能会使用目标处理器中的专用指令,或者可能会通过使用查找表而不是直接计算值或任何其他合理的优化来牺牲准确性以换取速度,所有这些都应记录在案。
这些绝对不是减少对特定编译器或cpu的依赖,事实上恰恰相反。它实际上添加了一个依赖项,因此这些可能包含在预处理器检查中,例如
#ifdef SOME_CPU_FLAG
#define MEMCPY __builtin_memcpy
#else
#define MEMCPY memcpy
传统的库函数,标准的memcpy
只是一个函数的调用。不幸的是,memcpy
经常被每个小副本调用,调用函数、洗牌几个字节和返回的开销是相当大的开销(特别是因为 memcpy
在处理未对齐内存、展开循环等的功能,以便在大型副本上表现出色)。
因此,为了让编译器优化这些,它需要 "know" 如何做,例如 memcpy
- 解决方案是在编译器中加入一个函数 "builtin" ,然后包含如下代码:
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 体系结构通常都有这些函数之一,对于调用 "real" memcpy
的条件或何时调用具有不同的配置使用内联 memcpy。]
这里的关键是您实际上可以编写自己的 memcpy
函数,它不是基于 __builtin_memcpy()
,它始终是一个函数,并且与正常 memcpy
[如果你改变它的行为很多你会有点麻烦,因为 C 标准库可能在几千个地方调用 memcpy
- 但是例如统计多少次memcpy
被调用,副本的大小可能就是这样一个用例]。
使用 __builtin_*
的另一个重要原因是它们提供的代码否则必须用内联汇编程序编写,或者可能根本不提供给程序员。 Setting/getting 特殊寄存器就是这样的东西。
还有其他技术可以解决这个问题,例如 clang
有一个 LibraryPass
假设库调用与其他替代方法具有共同的功能,例如因为 printf
很多"heavier" 比 puts
,它把合适的 printf("constant string with no formatting\n")
替换成 puts("constant string with no formatting")
,许多三角函数和其他数学函数在用常量调用时被解析为常见的简单值等
直接为 memcpy
或 sin
之类的函数调用 __builtin_*
可能是错误的做法 - 它只会降低代码的可移植性并且根本不确定更快。在没有其他情况下调用 __builtin_special_function
通常是某些棘手情况下的解决方案 - 但您可能应该将其包装在您自己的函数中,例如
int get_magic_property()
{
return __builtin_get_magic_property();
}
这样,当您移植到 Windows 时,您可以轻松地做到:
int get_magic_property()
{
#if WIN32
return Win32GetMagicPropertyEx();
#else
return __builtin_magic_property();
#endif
}