你需要的是一个CPU调度器。Agner Fog在他的Optimizing C++ manual的第13章“在不同指令集的多个版本中制作关键代码”中有10页的文字。他讨论了与GCC和ICC一起做这件事。 您只需要一个可执行文件,但您需要编译两个不同的目标文件,启用和不启用AES。然后,调度器确定哪个指令集可用,并基于此选择代码路径。 我试着用MSVC 2010 cpu dispatcher for visual studio for AVX and SSE来做这件事,但没有成功。我想我现在可以让它工作了。 编辑:在Agner Fog的vectorclass中,他有一个文件dispatch_example.cpp和instrset_detech.cpp,其中应该包含制作调度程序所需的大部分内容。您仍然需要弄清楚如何检测CPU是否具有AES。您需要增加intrset_detect. cpp文件。**根据wikipedia,如果CPU具有AES,则在读取CPUID时设置寄存器ECX中的位23。**Wikipedia也有读取CPUID的代码示例(除了instrset_detech.cpp-另一个很好的示例是文件cpuid.c中的https://github.com/Mysticial/Flops)
2条答案
按热度按时间0ve6wy6x1#
你需要的是一个CPU调度器。Agner Fog在他的Optimizing C++ manual的第13章“在不同指令集的多个版本中制作关键代码”中有10页的文字。他讨论了与GCC和ICC一起做这件事。
您只需要一个可执行文件,但您需要编译两个不同的目标文件,启用和不启用AES。然后,调度器确定哪个指令集可用,并基于此选择代码路径。
我试着用MSVC 2010 cpu dispatcher for visual studio for AVX and SSE来做这件事,但没有成功。我想我现在可以让它工作了。
编辑:在Agner Fog的vectorclass中,他有一个文件
dispatch_example.cpp
和instrset_detech.cpp
,其中应该包含制作调度程序所需的大部分内容。您仍然需要弄清楚如何检测CPU是否具有AES。您需要增加intrset_detect. cpp文件。**根据wikipedia,如果CPU具有AES,则在读取CPUID时设置寄存器ECX中的位23。**Wikipedia也有读取CPUID的代码示例(除了instrset_detech.cpp
-另一个很好的示例是文件cpuid.c中的https://github.com/Mysticial/Flops)js81xvg62#
在Solaris中实现这一点的一种方法是使用硬件功能库,这些库在运行时由链接器动态加载。
另一种选择是首先加载非法指令的陷阱处理程序,然后测试所需的机器语言指令。如果你碰到了陷阱,那么你就知道你不能使用优化的版本,而必须加载非优化的(或较少优化的)版本。
虽然我喜欢Andrew上面的建议,但我认为测试您需要的特定指令更安全。这样,您就不必为更新的CPUID输出而不断更新应用。
编辑添加:我意识到我应该提供一个例子。对于x64平台上的Solaris libc,我们提供了该库的硬件优化版本-三个版本用于32位,一个版本用于64位。我们可以通过在感兴趣的文件上运行
elfdump -H
来查看差异:猜猜上面哪个是AMD系统的,哪个是英特尔的?
Solaris链接器具有在调用进程' _init()之前在运行时加载正确的hwcap库的智能。