【问题标题】:How do I enable the SSE4.2 instruction set in Visual C++?如何在 Visual C++ 中启用 SSE4.2 指令集?
【发布时间】:2012-04-28 14:48:13
【问题描述】:

我在 Visual C++ 2010 中使用 OpenCV 中的简要描述符来匹配两个图像中的点。

the paper 关于BRIEF-descriptor 中写到可以加快速度:

“BRIEF 描述符使用汉明距离,这在现代 CPU 上可以非常快地完成,现代 CPU 通常提供特定指令来执行 XOR 或位计数 操作,就像最新的 SSE 指令集一样。”

启用 SSE4.2 后应该会加快速度。我的问题只是我如何在 Visual C++ 中做到这一点?

另一种方法是选择另一个支持 SSE4 的编译器。例如英特尔的 ICC。这真的有必要吗?

【问题讨论】:

  • 你区分 Visual Studio (IDE) 和 Visual C++(编程语言)吗? :)

标签: opencv visual-c++ hammingweight sse4


【解决方案1】:

不幸的是,它不是那样工作的。

可能会告诉 C/C++ 编译器使用项目中的特定指令集-> C/C++ -> 代码生成->启用增强指令集。但它几乎什么都不做,在你的情况下,绝对没有。这是因为某些 CPU 指令不能从 C 语句中轻松访问。一些编译器(如英特尔的)在这方面比其他编译器更好,但是对于你想要实现的目标,没有编译器足够聪明。

你要做的就是找到具体的算法,学习SSE指令,然后用这些指令手动重写算法。可以纯汇编编写,也可以使用intrinsic函数,可以从C/C++调用,编译时会发出SSE指令。

【讨论】:

  • 一个好的 C++ 库,如 libstdc++(GNU/Linux 的典型)或更新的 libc++ 将使用 popcnt 来实现 std::bitset<64>::count(),当它在编译时保证可用时。但是 MSVC 是围绕一个执行运行时调度的二进制模型设计的,并且它的库可能没有像 -arch:AVX 那样的优化(这意味着 SSE4.2 和因此 popcnt)所以实际上这个答案可能对 MSVC 是正确的。
【解决方案2】:

MSVC 编译器有一个/arch 选项,用于指定您希望程序面向的最低架构。将其设置为/arch:SSE2 将告诉编译器假设 CPU 支持 SSE2 指令,并且只要优化器确定它是合适的,它将自动使用它们。

但是,MSVC 没有 /arch:SSE4/arch:SSE42 选项。对标准库实现的一瞥表明/arch:AVX/arch:AVX2 也意味着 SSE4.2。例如,C++20 库函数std::popcount 的 MSVC 实现将对处理器进行运行时检查,看它是否可以使用 SSE4.2 popcnt 指令。但是,如果您以 AVX 为目标,它会跳过运行时检查并假设处理器支持它。

我认为 gcc 和 clang 确实有启用 SSE4 和 SSE4.2 的特定选项。 更新: Peter Cordes 在 cmets 中确认:“要专门启用 popcnt,-mpopcnt,或者对于 SSE4.2 -msse4.2,这意味着 popcnt。”

如果您不想依赖优化器和库实现来找到最佳指令,您也可以将内部函数用于内置指令。

【讨论】:

  • 对于 GCC/clang:-march=nehalem 或更高版本,或-march=znver1 (Zen) 将启用那些 CPU 支持的指令集(并调整为您指定的指令集),其中包括 popcnt。或-march=native。要专门启用 popcnt,-mpopcnt,或者对于 SSE4.2 -msse4.2,这意味着 popcnt。
  • 很高兴听到 MSVC 在std::popcount 中对 popcnt 提供了一些 CPU 功能支持。它是否还通过std::bitset<64>::count() 公开这一点,这是获得希望平台优化的popcount 的标准方法?
  • @PeterCordes:我没有专门研究过std::bitset,但如果它没有利用popcnt,我会感到惊讶。在查看了std::popcount 的实现之后,我使用 Godbolt Compiler Explorer 确认了使用 popcnt 生成的代码(并且/arch:AVX 消除了运行时检查和回退)。对std::bitset 执行相同操作应该很简单。
猜你喜欢
  • 2011-02-16
  • 1970-01-01
  • 2010-12-01
  • 2017-05-08
  • 2013-01-31
相关资源
最近更新 更多