C语言 我是否需要针对不同的指令集创建多个可执行文件?

dldeef67  于 2023-06-21  发布在  其他
关注(0)|答案(2)|浏览(121)

假设我有一个执行AES操作的程序。
一些高级CPU具有AES-NI指令集,而其他CPU则没有。
我必须把我的程序编译成两个可执行文件吗:A_with_aes_ni. exe和B_without_aes_ni. exe?

0ve6wy6x

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.cppinstrset_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

js81xvg6

js81xvg62#

在Solaris中实现这一点的一种方法是使用硬件功能库,这些库在运行时由链接器动态加载。
另一种选择是首先加载非法指令的陷阱处理程序,然后测试所需的机器语言指令。如果你碰到了陷阱,那么你就知道你不能使用优化的版本,而必须加载非优化的(或较少优化的)版本。
虽然我喜欢Andrew上面的建议,但我认为测试您需要的特定指令更安全。这样,您就不必为更新的CPUID输出而不断更新应用。
编辑添加:我意识到我应该提供一个例子。对于x64平台上的Solaris libc,我们提供了该库的硬件优化版本-三个版本用于32位,一个版本用于64位。我们可以通过在感兴趣的文件上运行elfdump -H来查看差异:

s11u1:jmcp $ elfdump -H /usr/lib/libc/libc_hwcap1.so.1 

Capabilities Section:  .SUNW_cap

 Object Capabilities:
     index  tag               value
       [0]  CA_SUNW_HW_1     0x86d  [ SSE MMX CMOV SEP CX8 FPU ]

 Symbol Capabilities:
     index  tag               value
       [2]  CA_SUNW_ID       hrt
       [3]  CA_SUNW_HW_1     0x40002  [ TSCP TSC ]

  Symbols:
     index    value      size      type bind oth ver shndx          name
       [1]  0x000f306c 0x00000225  FUNC LOCL  D    0 .text          gettimeofday%hrt
       [2]  0x000f2efc 0x00000165  FUNC LOCL  D    0 .text          gethrtime%hrt

Capabilities Chain Section:  .SUNW_capchain

 Capabilities family: gettimeofday
  chainndx  symndx      name
         1  [702]       gettimeofday
         2  [1]         gettimeofday%hrt

 Capabilities family: gethrtime
  chainndx  symndx      name
         4  [1939]      gethrtime
         5  [2]         gethrtime%hrt

s11u1:jmcp $ elfdump -H /usr/lib/libc/libc_hwcap2.so.1 

Capabilities Section:  .SUNW_cap

 Object Capabilities:
     index  tag               value
       [0]  CA_SUNW_HW_1     0x1875  [ SSE2 SSE MMX CMOV AMD_SYSC CX8 FPU ]

 Symbol Capabilities:
     index  tag               value
       [2]  CA_SUNW_ID       hrt
       [3]  CA_SUNW_HW_1     0x40002  [ TSCP TSC ]

  Symbols:
     index    value      size      type bind oth ver shndx          name
       [1]  0x000f253c 0x00000225  FUNC LOCL  D    0 .text              gettimeofday%hrt
       [2]  0x000f23cc 0x00000165  FUNC LOCL  D    0 .text          gethrtime%hrt

Capabilities Chain Section:  .SUNW_capchain

 Capabilities family: gettimeofday
  chainndx  symndx      name
         1  [702]       gettimeofday
         2  [1]         gettimeofday%hrt

 Capabilities family: gethrtime
  chainndx  symndx      name
         4  [1939]      gethrtime
         5  [2]         gethrtime%hrt

猜猜上面哪个是AMD系统的,哪个是英特尔的?
Solaris链接器具有在调用进程' _init()之前在运行时加载正确的hwcap库的智能。

相关问题