• 跳至主要導覽
  • 跳至主要內容
  • 跳至主要資訊欄
Office 指南

Office 指南

辦公室工作實用教學

  • Excel
  • Word
  • PowerPoint
  • Windows
  • PowerShell
  • R

Windows 使用 Cython 加速 Python 程式執行速度教學

介紹如何安裝與使用 Cython,結合 Python 與 C 語言的優點,提升程式的執行速度。

安裝 Cython

打開 Windows 的命令提示字元,使用 pip 安裝 cython 套件:

pip 安裝 cython
pip 安裝 cython

這樣就完成 Cython 的安裝了,不過由於 Cython 需要使用 C/C++ 編譯器,光只有安裝 Cython 是不夠的,必須另外安裝 Visual Studio 2019 才能使用。

安裝 Visual Studio 2019

從 Visual Studio 的網站下載 Visual Studio 2019 來安裝,個人使用的話下載免費的 Community 版本即可。

Visual Studio 2019
Visual Studio 2019

由於 Cython 只需要用到 Visual Studio 裡面的 C++建置工具,所以如果沒有用到整個 Visual Studio 的人,可以只下載 Build Tools for Visual Studio 2019 來安裝即可,這樣會省下很多硬碟空間。

Build Tools for Visual Studio 2019
Build Tools for Visual Studio 2019

以下是 Build Tools for Visual Studio 2019 的安裝步驟。
Step 1
實際安裝前,會先下載安裝程式。

Visual Studio Installer
Visual Studio Installer

Step 2
只需要選擇左上角的「C++ 建置工具」,其他的原件就不用安裝了。

安裝 C++ 建置工具
安裝 C++ 建置工具

Step 3
等待下載與安裝過程,跑完之後就完成安裝了。

Visual Studio Installer
Visual Studio Installer

Hello World

Cython 可以接受幾乎任何的 Python 程式碼,將其編譯成 C 的擴充模組,以提升執行速度,以下是將普通的 Python 程式碼以 Cython 編譯成擴充模組後,在一般的 Python 程式中引入執行的步驟。
Step 1
這一行是一般 Python 的 Hello World 程式碼:

print("Hello World")

將這一行程式碼儲存成 hello.pyx。

Step 2
建立一個 Python 指令稿 setup.py,內容如下:

from distutils.core import setup
from Cython.Build import cythonize

setup(
    ext_modules = cythonize("hello.pyx")
)

Step 3
建立一個工作目錄,把 hello.pyx 與 setup.py 兩個檔案放在此目錄下:

工作目錄
工作目錄

Step 4
開啟 Windows 的命令提示字元,切換至工作目錄,然後執行以下指令進行編譯:

python setup.py build_ext --inplace
用 Cython 編譯
用 Cython 編譯

執行完成後,應該會看到「已完成程式碼產生」的訊息,這樣就代表成功編譯完成了。

用 Cython 編譯
用 Cython 編譯

編譯完成之後,目錄中會產生許多檔案,其中 hello.cp37-win32.pyd 這個檔案就是實際執行時所需要的擴充套件檔(動態連結檔),而其餘的檔案都是編譯過程中產生的暫存檔。

工作目錄
工作目錄

Step 5
有了 hello.cp37-win32.pyd 這個擴充套件檔之後,就可以在一般的 Python 程式中以 import 的方式來引入執行:

import hello
引入執行擴充模組
引入執行擴充模組

以上是使用 Cython 編譯一般 Python 程式碼的步驟,但是由於這個例子很簡單,看不出 Cython 的效能優勢,要在計算量較大時使用 Cython 才會比較有效益。

搜尋質數範例

這一段 Python 程式碼是用來搜尋質數的函數,我們將示範如何使用 Cython 來加速運算速度,首先將這段程式碼儲存為 primes.py 與 primes_cython.pyx 兩個檔案,兩個內容完全相同。

def find(nb_primes):
    p = []
    n = 2
    while len(p) < nb_primes:
        # 檢查 n 是否為質數
        for i in p:
            if n % i == 0:
                break

        # 若是質數,則放進 p
        else:
            p.append(n)
        n += 1
    return p

接著編寫 setup.py 指令稿:

from distutils.core import setup
from Cython.Build import cythonize

setup(
    ext_modules = cythonize("primes_cython.pyx")
)

在 Windows 的命令提示字元中進行編譯:

python setup.py build_ext --inplace

建立一個測試用的 Python 指令稿 run.py,內容如下:

import primes
import primes_cython
import time

start = time.time()
p1 = primes.find(10000)
print('Python: %.2f sec' % (time.time() - start))

start = time.time()
p2 = primes_cython.find(10000)
print('Cython: %.2f sec' % (time.time() - start))

這段測試指令稿可用來比較普通 Python 與 Cython 的執行時間差異。

Python: 9.13 sec
Cython: 5.63 sec

指定變數型態

上面的質數範例中,我們只使用 Cython 進行編譯,並未修改原來的 Python 程式碼,所以加速並不是很明顯,如果想要獲得更好的效能,可以稍微更改一下程式碼,指定變數的類型,這樣加速的效果會更好。

我們將上面的程式碼修改一下,使用 cdef 指定變數型態後(用法請參考 Cython 官方文件),會變成這樣:

def find(nb_primes):
    # 以 cdef 指定變數型態
    cdef list p = []
    cdef unsigned int n = 2
    cdef unsigned int i
    while len(p) < nb_primes:
        for i in p:
            if n % i == 0:
                break

        else:
            p.append(n)
        n += 1
    return p

將這段程式碼儲存為 primes_cython2.pyx,使用 Cython 編譯的過程都一樣。然後在 run.py 中加入新的測試程式碼:

import primes
import primes_cython
import primes_cython2
import time

start = time.time()
p1 = primes.find(10000)
print('Python: %.2f sec' % (time.time() - start))

start = time.time()
p2 = primes_cython.find(10000)
print('Cython: %.2f sec' % (time.time() - start))

start = time.time()
p2 = primes_cython2.find(10000)
print('Cython2: %.2f sec' % (time.time() - start))
Python: 9.72 sec
Cython: 5.72 sec
Cython2: 0.37 sec

結果非常驚人,執行時間從原本的 9 秒縮短至 0.3 秒。

常見問題

如果在編譯 *.pyx 檔案時,出現這樣的錯誤:

error: Unable to find vcvarsall.bat

就代表 Cython 找不到編譯器,要安裝 Visual Studio 2019 或是 Build Tools for Visual Studio 2019。

參考資料:賈維斯的智慧工坊、Cython 官方文件

分類:Python, Windows

主要資訊欄

搜尋

近期文章

  • Python 使用 PyAutoGUI 自動操作滑鼠與鍵盤
  • Ubuntu Linux 以 WireGuard 架設 VPN 伺服器教學與範例
  • Linux 網路設定 ip 指令用法教學與範例
  • Windows 使用 TPM 虛擬智慧卡保護 SSH 金鑰教學與範例
  • Linux 以 Shamir’s Secret Sharing 分割保存金鑰教學與範例
  • Linux 以 Cryptsetup、LUKS 加密 USB 隨身碟教學與範例
  • Linux 以 Cryptsetup 與 LUKS 加密磁碟教學與範例
  • Linux 使用 age 簡潔的加密、解密工具使用教學與範例

推薦網站

  • Udemy 線上教學課程
  • Coursera 線上教學課程

關注本站

  • 電子郵件
  • Facebook

公益

  • 家扶基金會
  • 台灣世界展望會
  • Yahoo 奇摩公益
  • igiving 公益網
  • 兒福聯盟

Copyright © 2021 · Office Guide