我正在构建一个安装程序/下载程序来检测架构并下载使用该架构编译的主要可执行文件的版本。如果它还不存在,它将在服务器上即时编译。
我可以轻松获取 CPU 名称,例如“Intel(R) Core(TM) i9-10900KF CPU @ 3.70GHz”,但如何将其转换为 MinGW 的 -march 和 -mtune 设置的正确字符串?
我不能依赖任何依赖项,它需要能够使用可由安装程序运行的独立脚本或可执行文件来确定这一点,以确定正确的字符串。或者我可以使用所有 CPU 名称的大量列表转换为 -march 字符串,但我在哪里可以找到它?
编辑:我不能使用 -march=native 因为编译器不在客户端机器上。我正在做的是通过安装程序检测客户机上的体系结构,然后在服务器上针对它们的体系结构进行编译。所以我不能使用 -march=native.
如果你可以分发 MinGW 的
gcc.exe
编译器驱动程序(只是那个小文件和它所依赖的库,没有多兆字节的语言前端 cc1.exe
,cc1plus.exe
等)那么你可以在客户端上运行它带有-###
选项的机器是这样的:
gcc.exe -### -xc - -E -march=native
并从输出的
-m
行中获取各种--param
和cc1.exe
选项。
要了解
-march=native
的工作原理,请查看 GCC 源代码中的 driver-i386.cc 和 common/config/i386。如果你从那里复制,我建议将结果作为一个独立的工具,你可以在 GPL 下分发,尊重这些文件的原始许可。
您可以使用 cpuid 指令查询 CPU 的有关其特性的信息。这是带有相应标志的大部分功能。
std::vector<std::string> get_cpu_flags() {
std::vector<std::string> flags;
int info[4];
__cpuid(info, 1);
std::bitset<32> edx_features(info[3]);
std::bitset<32> ecx_features(info[2]);
if (edx_features[23]) flags.push_back("mmx");
if (edx_features[25]) flags.push_back("sse");
if (edx_features[26]) flags.push_back("sse2");
if (ecx_features[0]) flags.push_back("sse3");
if (ecx_features[9]) flags.push_back("ssse3");
if (ecx_features[19]) flags.push_back("sse4_1");
if (ecx_features[20]) flags.push_back("sse4_2");
if (ecx_features[28]) flags.push_back("avx");
if (ecx_features[12]) flags.push_back("fma");
__cpuid(info, 7);
std::bitset<32> ebx_features(info[1]);
std::bitset<32> ecx_features_level7(info[2]);
if (ebx_features[5]) flags.push_back("avx2");
if (ebx_features[16]) flags.push_back("avx512f");
if (ebx_features[17]) flags.push_back("avx512dq");
if (ebx_features[21]) flags.push_back("avx512ifma");
if (ebx_features[26]) flags.push_back("avx512pf");
if (ebx_features[27]) flags.push_back("avx512er");
if (ebx_features[28]) flags.push_back("avx512cd");
if (ebx_features[30]) flags.push_back("avx512bw");
if (ebx_features[31]) flags.push_back("avx512vl");
if (ecx_features_level7[1]) flags.push_back("avx512vbmi");
if (ecx_features_level7[14]) flags.push_back("avx512vbmi2");
if (ecx_features_level7[30]) flags.push_back("avx512_vnni");
return flags;
}