作者:qzq9037091 | 来源:互联网 | 2023-02-01 16:02
我编写了一个库,我使用CMake来验证MMX,SSE,SSE2,SSE4,AVX,AVX2和AVX-512的标头是否存在.除此之外,我检查是否存在指令,如果存在,我添加必要的编译器标志,-msse2 -mavx -mfma等.
这一切都非常好,但我想部署一个二进制文件,它适用于各代处理器.
问题:是否有可能告诉编译器(GCC)每当使用SIMD优化函数时,它必须为架构列表生成代码?当然还有高级分支机构
我在想类似于编译器如何为函数生成代码,其中输入指针是4或8字节对齐的.为了防止这种情况,我使用__builtin_assume_aligned
宏.
什么是最佳做法?多个二进制文件?命名?
1> nemequ..:
只要你不关心可移植性,是的.
最近的GCC版本比使用target_clones函数属性我知道的任何其他编译器更容易.只需添加属性,以及要为其创建版本的目标列表,GCC将自动创建不同的变体,以及在运行时自动选择版本的调度函数.
如果你想要更多的可移植性,你可以使用target属性,clang和icc也支持,但你必须自己编写调度函数(这并不难),并多次发出函数(通常使用一个宏,或反复包括标题).
AFAIK,如果您希望代码与MSVC一起使用,则需要使用不同选项的多个编译器调用.
2> Tim..:
如果您只是在说要让编译器生成SSE / AVX等指令,并且您有“通用”代码(即您没有使用内在函数进行显式矢量化,或者有很多代码可供编译器发现和使用)。自动向量化),那么我应该警告您,编译整个代码库的AVX,AVX2或AVX512的运行速度可能会比SSE版本的编译速度慢得多。
当检测到使用寄存器的上半部分的AVX操作码时,CPU会为电路的上半部加电(否则将断电)。这会消耗更多的功率,产生更多的热量并降低芯片的基本时钟速度,具体取决于高功率和低功率操作码的混合,通常会降低10-20%,因此您可能会立即失去15%的性能,然后在开始发现任何收益之前,要进行很多矢量化处理,以弥补此性能缺陷。
请参阅此线程中我的详细解释和参考。
另一方面,如果您正在使用内在函数进行显式矢量化并且您确定具有足够大的AVX爆发等特性,那么我已经成功编写了代码,告诉MSVC为SSE2编译(x64的默认设置),但是然后我会动态检查CPU功能,并将某些功能切换到使用AVX内在函数实现的代码路径。
MSVC允许这样做(它会产生警告,但您可以使这些警告消失),但是在GCC 4.9下很难使用相同的技术,因为仅当使用适当的代码生成标志时,编译器才声明内在函数。[更新:@nemequ下面说明如何使用属性装饰功能在gcc下进行此工作]根据GCC的版本,您可能必须编译带有不同标志的文件才能获得可用的系统。
哦,您还必须注意AVX-SSE转换(当您离开代码的AVX部分以返回SSE代码时,请致电VZEROUPPER)-可以做到,但是我发现了解CPU的影响比我本来要大设想的。