商品等のご購入はAmazonがおすすめ

Pythonのお手軽な高速化方法 part3

プログラミング言語

ctypes

ctypesとは

ctypes --- Python 用の外部関数ライブラリ
ソースコード: Lib/ctypes ctypes は Python のための外部関数ライブラリです。このライブラリは C と互換性のあるデータ型を提供し、動的リンク/共有ライブラリ内の関数呼び出しを可能にします。動的リンク/共有ライブラリ...

簡単に言うとC言語製の関数を使用するためのライブラリです。

共有ライブラリ(Windowsでは「.dll」、Linuxでは「.so」など)を読み込む形で使用されます。

使用方法

使用したい関数を記述したCコードを用意します。

int fib(int n) {
    if (n < 2) return n;
    return fib(n - 1) + fib(n - 2);
}

そして、共有ライブラリを生成します。gccの場合は

gcc fib.c -shared -o fib.dll

このように「-shared」オプションを付けて生成できます。

あとは「LoadLibrary()」でライブラリを読み込めば使用可能となります。

import ctypes
def c_fib(n):
    libc = ctypes.cdll.LoadLibrary("./fib.dll")
    return libc.fib(n)

print(c_fib(40))

実行速度

パターン実行速度(秒)
Python (3.13.1) のみで計算17.3
計算部分は全てctypes0.7

Nuitka

Nuitkaとは

GitHub - Nuitka/Nuitka: Nuitka is a Python compiler written in Python. It's fully compatible with Python 2.6, 2.7, 3.4-3.13. You feed it your Python app, it does a lot of clever things, and spits out an executable or extension module.
Nuitka is a Python compiler written in Python. It's fully compatible with Python 2.6, 2.7, 3.4-3.13. You feed it your Py...

NuitkaはPythonコードをC言語コードにコンパイルしてくれるコンパイラで、記事執筆現在ではPython2.6~2.7、Python3.4~3.13まで対応しており、サードパーティライブラリ等もわずかに対応してます。

nuitka plugin list

C言語コードにコンパイルするといっても以前紹介したCodonのようにちゃんとコンパイルするわけではなく、高速化はよくて3割程度だと思います。

使用方法

Cコンパイラ

比較的新しめのCコンパイラが必要となります。

MinGW64が使用可能とドキュメントにはありますが、筆者がインストールしたものは使えず、Nuitkaがダウンロードしてそっちを使わされたあげく、セキュリティソフトにウィルス判定されてコンパイルに失敗しました。

特にオプションで指定しなければVisual Studio 2022のコンパイラ(cl.exe)が使用されたのでMinGWでうまくいかないときはVisual Studioをインストールしてみてください。

「nuitka –version」コマンドで使用される環境一覧が取得できます。

nuitka version

ビルドコマンド

以下にビルドコマンド例を示します。

nuitka --standalone --enable-plugin=tk-inter --windows-icon-from-ico="D:\icons\領.ico" --output-filename="amazon" --output-dir="amazon" --windows-console-mode="disable" .\main.py

オプション

主なオプション説明
–standalonePython環境が整ってなくても動くようにする。配布用にするなら必須。
「XX.dist」フォルダを丸ごと渡せばOK。
–onefile配布用フォルダごとまるっと一つの実行ファイル(windowsなら.exe)にする。
「–standalone」コマンドも含まれるのでこのオプションを付与した場合は不要。
実行環境を一時ファイルに解凍してから起動するようになるため、若干遅くなる。
–enable-plugin有効にするプラグインを指定する。
必要なものは指定しないとエラーが出るので、エラーログに従って指定すれば大体うまくいく。
うまくいかないときは使用不可なライブラリ等を使用してるか何かしらのバグ。
–windows-icon-from-ico実行ファイルのアイコンを指定できる。
OS事に異なる。
これはWindows用。
–windows-console-modeGUIアプリの場合にコンソールが不要なら「disable」を指定する。
これもOS事で異なるオプション。
–output-filename実行ファイル名を指定できる。
指定しなくても後から名前を変えればいいからどうでもいいオプション。
–output-dir「XX.build」と「XX.dist」フォルダなどの出力フォルダ名を指定できる。
出力環境をまとめたい几帳面な人用。

他にも大事なオプションはあるけどまあどうせアップデートで今後どんどん変更されるだろうからこれくらいで許してください。

実行速度

以下に実行速度の例を挙げておきます。

def fib(n):
    if n < 2:
        return n
    return fib(n - 1) + fib(n - 2)

print(fib(40))
言語実行速度(秒)
Python (3.13.1)17.3
Nuitka (2.5.8)12.4
C (gcc 14.2.0)0.7
C (gcc 14.2.0 最適化オプション)0.4

このように多少は高速化します。

import削減

アプリ開発時によくやるのですが、「test.py」とか「tmp.py」みたいなちょっとしたコードの動作確認用モジュールを作るんですよね。

そこでやりがちなのが「過去使ったライブラリやパッケージのimportをそのままにしておく」ことです。

これが意外と処理時間に関係してきます。

import os
import sys
import datetime
from math import log
import python_bitbankcc
import pandas as pd
import bitbank_ui
from pprint import pprint
import config
import judge_buysell
import trade_log

def main():
    print("aaa")

if __name__ == '__main__':
    main()

ちょうど個人用アプリで使ってるtest.pyがあるのでそこから引用してみますが、上記のようにやたらめったらimportしたものと、

def main():
    print("aaa")

if __name__ == '__main__':
    main()

無駄なimportを省いたものとでは以下のように明確に処理時間に差が出ます。

無駄なimport処理時間(秒)
あり2.1901373
なし0.0556866

積み重なるとかなりの処理時間になるので、できるだけ無駄なものは省きましょう。

まとめ

次はGIL解除版Pythonでも試そうかな?

コメント

タイトルとURLをコピーしました