GCC 定义了许多宏来在编译时确定使用-march. 您可以在此处的源代码中找到完整列表。很明显,GCC 没有为RDTSCP(或什至RDTSC为此)定义这样的宏。支持的处理器RDTSCP列在:什么是包含对 RDTSCP 支持的 gcc cpu 类型?.
因此,您可以制作自己的(可能不完整的)列表微体系结构支持RDTSCP. 然后编写一个构建脚本来检查传递给的参数-march并查看它是否在列表中。如果是,则定义一个宏,例如__RDTSCP__并在您的代码中使用它。我认为即使您的列表不完整,也不应该损害您代码的正确性。
不幸的是,RDTSCP尽管英特尔数据表讨论了 AVX2 等其他功能,但它们似乎并未指定特定处理器是否支持。
这里的一个潜在问题是,无法保证实现特定微体系结构(例如 Skylake)的每个处理器都支持RDTSCP. 我不知道这样的例外。
相关:包含对 RDTSCP 支持的 gcc cpu 类型是什么?.
要在运行时确定 RDTSCP 支持,可以在任何 x86 操作系统上支持 GNU 扩展(GCC、clang、ICC)的编译器上使用以下代码。 cpuid.h带有编译器,而不是操作系统。
#include <cpuid.h>
int rdtscp_supported(void) {
unsigned a, b, c, d;
if (__get_cpuid(0x80000001, &a, &b, &c, &d) && (d & (1<<27)))
{
// RDTSCP is supported.
return 1;
}
else
{
// RDTSCP is not supported.
return 0;
}
}
Run Code Online (Sandbox Code Playgroud)
__get_cpuid()运行 CPUID 两次:一次检查最大级别,一次使用指定的叶值。如果请求的级别甚至不可用,它就会返回 false,这就是为什么它是&&表达式的一部分。您可能不想每次都在 rdtscp 之前使用它,只是作为变量的初始化程序,除非它只是一个简单的一次性程序。在 Godbolt 编译器浏览器上查看。
对于 MSVC,请参阅如何检测 Visual C++ 中的 rdtscp 支持?对于使用其内在的代码。
对于 GCC 知道的某些 CPU 功能,您可以使用__builtin_cpu_supports检查在启动早期初始化的功能位图。
// unfortunately no equivalent for RDTSCP
int sse42_supported() {
return __builtin_cpu_supports("sse4.2");
}
Run Code Online (Sandbox Code Playgroud)