使用 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?