使用 qmake 成功编译 SSE 指令(但无法识别 SSE2)

Posted

技术标签:

【中文标题】使用 qmake 成功编译 SSE 指令(但无法识别 SSE2)【英文标题】:Successful compilation of SSE instruction with qmake (but SSE2 is not recognized) 【发布时间】:2013-09-06 08:38:18 【问题描述】:

我正在尝试编译和运行从 Unix 迁移到 Windows 的代码。我的代码是纯 C++,不使用 Qt 类。在 Unix 中没问题。

我还使用 Qt creator 作为 IDE,并使用 qmake.exe-spec win32-g++ 进行编译。因为我的代码中有sse 指令,所以我必须包含emmintrin.h 标头。

我补充说:

QMAKE_FLAGS_RELEASE += -O3 -msse4.1 -mssse3 -msse3 -msse2 -msse

QMAKE_CXXFLAGS_RELEASE += -O3 -msse4.1 -mssse3 -msse3 -msse2 -msse

.pro 文件中。 我已经能够毫无错误地编译我的代码。但在运行某些包含__m128 或类似的函数时会出现运行时错误。

当我打开emmintrin.h 时,我看到了:

#ifndef __SSE2__
# error "SSE2 instruction set not enabled"
#else

#else之后没有定义。

我不知道如何在我的电脑上启用SSE

平台:Windows Vista

系统类型:64位

处理器:intel(R) Core(TM) i5-2430M CPU @ 2.40Hz

有人知道解决办法吗?

提前致谢。

【问题讨论】:

您能否更具体地了解运行时错误?请复制并粘贴实际的错误消息。 不是运行时错误的问题。虽然访问冲突。主要问题是 __SSE__ 没有定义。我确定其余的代码。 是什么让你认为__SSE__ 没有定义?您似乎对在标题中看到的内容感到困惑,这与此处无关。 是的,我想我很困惑。因为我在 Qt creator 中看到灰线,这意味着这些线不会被编译。此外,IDE 说 __m128 不是类型名称。但是在调试模式下逐步运行代码时。 SSE 部分代码运行良好。我认为问题出在其他地方。它在执行_mm_load_ps() 函数时崩溃。可能是由于输入分配错误。顺便说一句,我想知道我的机器是否支持该功能或......? 这就是我要求您发布实际运行时错误消息的原因 - 这听起来像是典型的 SSE 未对齐数据问题。尝试正确对齐数据或使用_mm_loadu_ps 而不是_mm_load_ps 【参考方案1】:

听起来您的数据不是 16 字节对齐的,这是 SSE 加载(例如 mm_load_ps)的要求。您可以:

使用_mm_loadu_ps 作为临时解决方法。在较新的 CPU 上,此类未对齐负载的性能影响相当小(在较旧的 CPU 上更为显着),但仍应尽可能避免

修复内存对齐问题。在 Windows/Visual Studio 上,您可以使用 declspec(align(16)) 属性进行静态分配或使用 _aligned_malloc 进行动态分配。对于 gcc 和大多数其他文明平台/编译器,前者使用__attribute__ ((align(16))),后者使用posix_memalign

【讨论】:

我编写了一个 Windows 程序来测量 _mm_loadu_ps 损失。该程序使用 _mm_loadu_ps 或 _mm_load_ps 从数组加载浮点数,并显示每个浮点数的执行时间。基准循环还包含一个添加指令,以防止优化器移除负载。使用 mingw64/gcc 4.8 或 Visual Studio 构建 SB (@4.0GHz) 的结果相同:_mm_load_ps 每循环 0.75 ns,_mm_loadu_ps 每循环 0.78 ns。因此,如果我正确地编写了测试代码,Sandy Bridge 在减少未对齐的负载开销方面做得非常出色。源代码在这里:notabs.org/misc/alignment.7z. @ScottD,所以我在 Linux 下的 i5-3317U CPU @ 1.70GHz 上运行了你的代码(经过一些修改),我得到了 1.22ns 未对齐和 1.17 对齐。这大约慢了 4%。基于 Paul 的陈述,“像这样的未对齐负载的性能影响相当小(在较旧的 CPU 上更为显着),但如果可能,仍应避免这种情况。”是准确的。我必须更仔细地检查一下。 @redrum,移植我知道的代码很痛苦。我尝试了一些更大的数组大小,结果是相同的,直到总缓冲区大小超过 8MB L3 缓存大小。之后,_mm_loadu_ps 和 _mm_load_ps 的速度一样慢。 AMD 处理器 A6-3650 也可以很好地处理未对齐。但即便如此,对齐数据是有益的,并且为提高旧处理器的可移植性和友好性付出了很小的代价。正如 Paul R 所解释的,当阵列未对齐时,宝贵的 L1 缓存空间会被浪费,这可能会影响某些循环的性能。 @PaulR,感谢您提供的信息。也许这就是我过去所看到的(当我第一次开始编写我的 GEMM 代码时)。我似乎记得负载未对齐时性能更差,从那时起我就没有费心测试未对齐的内存。如果我设法重现/恢复我所做的测试,我会发布一个关于它们的 SO 问题。 @ScottD,让你的代码跨平台/编译器相当容易。 Use _mm_malloc instead of _aligned_malloc(这是我以前的 SO 生活中的问题)以及 omp_get_wtime()(而不是 windows 性能计时器),您的代码将在 GCC、MinGW、MSVC 和 ICC 以及 Linux 和 Windows(可能还有 OSX)上运行)。我没有实现的唯一部分是更改任务优先级。我对此没有很好的解决方案,所以我将其注释掉。

以上是关于使用 qmake 成功编译 SSE 指令(但无法识别 SSE2)的主要内容,如果未能解决你的问题,请参考以下文章

如何在Windows上使用SSE和AVX指令编译Tensor Flow?

在 Visual Studio 中检测 SSE/SSE2 指令集的可用性

使用 Qt Creator / qmake / MinGw 的预编译标头无法在调试版本中工作

如何使用 SSE4.2 和 AVX 指令编译 Tensorflow?

如何使用 SSE4.2 和 AVX 指令编译 Tensorflow?

如何使用 SSE4.2 和 AVX 指令编译 Tensorflow?