Pyslvs 編譯進度 - 演算法 - Windows 版編譯:

  • 演算法函式庫除錯

  • 編譯方法

Pyslvs 編譯進度 - 演算法 - Windows 版編譯

演算法函式庫除錯

之前嘗試過在 Widows 平台編譯學長的 Cython 函式庫,但是使用 MinGW 和 VS 都出錯,於是上網了解一下關鍵原因。

在官方說明中提到,目前尚未支援 Windows 的 64 位元 GNU,而使用 MinGW32 的話,會造成 64 位元的 Python 無法輸入或讀取任何資訊(進位制不同)。

https://github.com/cython/cython/wiki/CythonExtensionsOnWindows#less-useful-information

因此在 Windows 平台中只能使用微軟提供的 SDK 協助編譯了。

使用 Visual Studio Community 客戶端安裝 Windows SDK 即可,若是 Python 認不得 2012 以上的版本,必須編輯 Anaconda 的 Lib\distutils\ 資料夾中的 cygwinccompiler.py,在大約 85 行的位置插入以下程式碼:

elif msc_ver == '1700':
    # Visual Studio 2012 / Visual C++ 11.0
    return ['msvcr110']
elif msc_ver == '1800':
    # Visual Studio 2013 / Visual C++ 12.0
    return ['msvcr120']
elif msc_ver == '1900':
    # Visual Studio 2015 / Visual C++ 14.0
    return ['vcruntime140']

Cython 在編譯時才會找到 SDK 的工具。

編譯後,執行 test.py 時出現了類似 IndexError: index 250 is out of bounds for axis 0... 的訊息,顯示某個 List 超出可讀取範圍。

在不斷測試與檢查之後發現是 Cython 從 C 語言 import 的 random 函數有問題。

from libc.stdlib cimport rand, RAND_MAX, srand

cdef double randV():
    return rand()*1.0 / RAND_MAX

這個是產生亂數用的 function,在 Windows 下,回傳值某些時候會大於 1,這就導致長度 250 的 list 出現 [250] 的選項。

為了避免這個狀況發生,改寫上面的函式成下面的樣子:

cdef double randV():
    randomNum = rand()*1.0 / RAND_MAX
    if randomNum>=1: randomNum -= 0.1
    return randomNum

這裡使用迭代運算而非重新指定值,速度會比較快一點。

需要修改的檔案為 rga.pyxde.pyx,其他函式庫都沒問題。

但是因為 Windows 平台多加了判斷式,還有其他因素,運算時間慢上 1 倍(中間的螢火蟲演算法完全相同)。以下是相同題目的運算結果:

編譯方法

由於加入了 Cython 的程式庫,原本的編譯方式又沒辦法使用了,會出現「pythoncom」匯入的錯誤。

用兩種方式重新編譯後,發現在 PyInstaller 的資料夾(dist)中執行它的主程式,會顯示找不到 py35w 的核心。

於是就將 cxFreeze 的 core 資料夾複製到 PyInstaller 的資料夾中,再啟動主程式就可以使用了,也不會出現任何錯誤。

此方法已經套用到 winBuild.bat 中。

目前暫時將 PyInstaller 的 -w 參數拿掉,方便在 Windows 平台查看 console 資訊。


Comments

comments powered by Disqus