2013-03-20 109 views
8

我有一個使用CPU專用功能的Python擴展,如果可用的話, 。這是通過運行時檢查完成的。如果 硬件支持POPCNT指令,那麼它會選擇一個內部循環的 實現,如果SSSE3可用,則 它選擇另一個,否則它將回退到我的性能嚴重的內核的通用版本 。 (在這個內核中花費了95%+的時間是 )。如何在distutils中爲一個Python/C擴展文件指定不同的編譯器標誌?

不幸的是,我沒有想到會出現失敗模式。 I 使用-mssse3和-O3來編譯所有的C代碼,即使 只有一個文件需要那個-mssse3選項。

因此,其他文件編譯期望 SSSE3將存在。這會導致一個段錯誤的線

start_target_popcount = (int)(query_popcount * threshold); 

因爲編譯器fisttpl使用,這是一個SSSE-3指令。畢竟,我告訴它假設ssse3存在。

Debian的打包了我的包最近就遇到了這個問題,因爲 的試驗機有哪些瞭解-mssse3和 產生記住與代碼GCC,但機器本身有沒有這些指令的 舊的CPU。

我想要一個解決方案,其中相同的二進制文件可以在較舊的機器上工作,並在較新的機器上工作,即Debian維護人員可以使用該發行版。

理想情況下,我想說只有一個文件編譯爲 和-mssse3選項。由於我的CPU專用選擇器代碼 不是該文件的一部分,因此除非CPU支持is,否則不會執行SSSE-3代碼 。

但是,我找不出任何方式來告訴distutils, 一組編譯器選項是特定於單個文件。

這可能嗎?

+0

+1因爲這多年來一直困擾着我。我認爲這是不可能的,所以任何一種方式的確定性答案都會很有趣。 – danodonovan 2013-03-20 15:32:55

+0

在考慮danodonovan的答案時,我意識到黑客應該有一個「CC」包裝器,它爲特定文件插入正確的標記。不雅,但對Debian來說可能就足夠了。 – 2013-03-20 16:21:32

+0

我最近發現一些快樂合併CMake和distutils,使用CMake生成與擴展名鏈接的靜態庫。你可以做類似的事情。請參閱我們的setup.py:https:// github。com/CoolProp/CoolProp/blob/master/wrappers/Python/setup.py – ibell 2015-02-24 06:35:58

回答

5

一個非常難看的解決方案是創建兩個(或更多Extension)類,一個用於保存SSSE3代碼,另一個用於保存其他所有內容。然後你可以在Python層中整理界面。

c_src = [f for f in my_files if f != 'ssse3_file.c'] 

c_gen = Extension('c_general', sources=c_src, 
       libraries=[], extra_compile_args=['-O3']) 

c_ssse3 = Extension('c_ssse_three', sources=['ssse3_file.c'], 
       libraries=[], extra_compile_args=['-O3', '-mssse3']) 

,並在__init__.py某處

from c_general import * 
from c_ssse_three import * 

當然,你不需要我寫出來的代碼!而且我知道這不是DRY,我期待着閱讀更好的答案!

+0

不幸的是,它是決定運行哪個計算內核的C代碼,所以你的建議雖然可行,但變得相當困難。基本上,我需要實現C共享庫,或者我必須有某種動態API來註冊可用的計算內核。與指定每個文件標誌的理想解決方案相比,這兩者都有很多工作。 – 2013-03-20 16:18:13

相關問題