如何在新CPU上利用AVX2,同时支持旧CPU?
How to take advantage of AVX2 on new CPUs while also supporting old CPUs?
我有一些图像处理算法,我在三个版本中实现了它:
- 使用 x64 指令集(rax、rbx、...寄存器)
- 使用 SSE 指令集(xmm 寄存器)
- 使用 AVX2 指令集(ymm 寄存器)
每个优化步骤都会提高性能。但是,我需要在仅支持 SSE 的旧 CPU 上运行它(我在 Visual Studio 上使用 x64 平台,所以我所有的 CPU 都支持 SSE)。
在Visual Studio中,有一个名为"启用增强指令集"的设置,我必须将其设置为/arch:AVX2
,以便在较新的CPU上获得最佳性能。但是,使用此设置,可执行文件在我的旧 CPU 上崩溃。如果我将"启用增强指令集"设置为/arch:SSE2
,那么我的可执行文件可以在较旧的 CPU 上运行,但我在较新的 CPU 上无法获得最佳性能。
我使用较新的 CPU 测量了编译器标志和指令集的所有组合的执行速度。下表显示了摘要。
指令集 || 编译标志 我用的|| /arch:SSE/arch:AVX2 ----------------++------------------------------------ x64 || 不好 (4.6) 不好 (4.5) 上交所 || 正常 (1.9) 差 (5.3) AVX2 || 不好 (3.2) 好 (1.4)
我的矢量化代码使用内部函数,如下所示:
// AVX2 - conversion from 32-bit to 16-bit
temp = _mm256_packus_epi32(input[0], input[1]);
output = _mm256_permute4x64_epi64(temp, 0xd8);
// SSE - choosing one of two results using a mask
result = _mm_blendv_epi8(result0, result1, mask);
我猜如果Visual Studio获得/arch:AVX2
编译标志,它会执行所有必要的AVX2特定优化,例如发出vzeroupper
。所以我不明白如何使用相同的编译可执行文件在两种类型的 CPU 上获得最佳性能。
这可能吗?如果是,我需要向Visual Studio编译器提供哪些编译标志?
英特尔这样做的方式是 CPU 调度(查看英特尔编译器文档中的ax
标志)。ax
标志特定于英特尔编译器,并进行隐式 CPU 调度。它在VS上不可用,因此您必须手动执行此操作。
在代码开始时,检查 CPU 功能并在某处设置一些全局标志。
然后,当您调用其中一个函数时,首先检查标志状态以查看您实际要调用的函数。
因此,您最终会得到不同风格的函数。为了解决这个问题,您可以将它们放在不同的特定命名空间中(如 libsimdpp 所做的),或者手动修改函数名称(如英特尔编译器所做的)。
此外,任何 64 位的 CPU 都通过构造支持 SSE2,因此情况 1 不存在。
- 编译时未启用intel oneApi CUDA支持
- POCO::PostgreSQL:如何将std::vector支持添加到`Binder::bind`
- 使用CMake检测支持的C++标准
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 为什么istream不支持右值提取
- 当我编译webrtc服务器时,Windows上只支持clang-cl
- 扩展光电二极管探测器以支持多个传感器
- MSVC是否支持C++11样式的属性而不是__declspec
- 在使用GPU支持编译Tensorflow时,会遇到CUDA_TOOLKIT_PATH未绑定变量
- 当使用比格式支持的精度更高的精度来显示数字时,会写出什么数据
- 在模拟器中使用并集来模拟CPU寄存器有多合适
- 编写一个函数以使用 n 百分比的 CPU 使用率
- 如何禁用 CPU 的无序执行
- 您选择的 CPU 不支持 x86-64 指令集
- 强制 Dlib python 仅使用 CPU 支持进行安装;在具有 Cuda 和所有内容的 GPU 机器上
- 如何在新CPU上利用AVX2,同时支持旧CPU?
- 如何检测 CPU 是否支持英特尔防盗技术
- 使用串行端口线程进行 CPU 支持
- 根据可用的 CPU 支持使用不同的类
- 如何检查CPU是否支持SSE3指令集