我有一个Python扩展,它使用CPU特有的特性,
如果有的话。这是通过运行时检查完成的。如果
硬件支持POPCNT
指令,然后选择一条
实现我的内部循环,如果SSSE3可用,那么
它会选择另一个版本,否则会返回到通用版本
我的性能关键内核。(大约95%以上的时间是
在这个内核中花费的时间。)
不幸的是,有一种我没有预料到的失败模式。我
使用-mssse3
和-O3
编译所有C代码,即使
只有一个文件需要-mssse3
选项。因此,编译其他文件时预期SSSE3将存在。这会导致线路出现SEG故障:
start_target_popcount = (int)(query_popcount * threshold);
因为编译器使用了fisttpl
,这是一条SSSE3指令。
毕竟,我告诉它假设SSSE3存在
我的软件包的Debian打包程序最近遇到了这个问题,
因为测试机器有一个理解-mssse3
和
生成代码时考虑到这一点,但机器本身有一个
没有这些指令的旧CPU
我想要一个解决方案,使相同的二进制文件可以在较旧的机器上工作 在较新版本上,Debian维护人员可以将其用于该发行版
理想情况下,我想说只编译一个文件
使用-mssse3
选项。因为我的CPU特定选择器代码
不是此文件的一部分,将不会执行任何SSSE3代码
除非CPU支持它
然而,我想不出任何方法来告诉distutils
一组编译器选项特定于单个文件。
这可能吗
一个非常丑陋的解决方案是创建两个(或更多
Extension
)类,一个用于保存SSSE3代码,另一个用于保存其他所有代码。然后可以在python层中整理接口在某处
__init__.py
你当然不需要我来写代码!我知道这不是干的,我期待着阅读更好的答案
已经5年了,但我找到了一个比我的“CC”包装更喜欢的解决方案
“build_ext”命令创建一个self.compiler实例。compile.compile()方法获取要编译的所有源文件的列表。基类进行一些设置,然后有一个编译器。_compile()钩子用于具体的编译器子类,以实现实际的每个文件编译步骤
我觉得这是足够稳定的,我可以拦截代码在那一点上
我从distutils.command.build\u ext.build\u ext派生了一个新命令,该命令调整了self.compiler.\u compile以包装绑定类方法,并将一个一次性函数附加到实例:
然后,我告诉setup()使用以下命令类:
不幸的是,OP的解决方案只适用于Unix编译器。这是一个交叉编译器:
(MSVC不支持自动生成SSSE3代码,因此我将使用AVX作为示例)
有关指定编译器的交叉编译器方法,请参见my answer here/链接器选项
相关问题 更多 >
编程相关推荐