English | 中文 | 日本語 | Français | Deutsch
このプロジェクトは、Fibonacci 計算を C++ で実装し、Python のネイティブ拡張モジュールとして呼び出す方法を示します。
ビルド後は、Python から次のように使用できます。
import fibonacci_cpp
print(fibonacci_cpp.fibonacci(10)) # 55- Python 3.x
- CMake 3.18 以降
- MinGW、MSVC、Clang などの C++17 コンパイラ
必要なコマンドを確認します。
python --version
cmake --version
g++ --versionPython 拡張モジュールは、ビルド時と実行時で同じ Python バージョンを使う必要があります。このプロジェクトの CMake 設定は、現在のコマンドライン PATH にある python を優先するため、cmake --build build で生成されたモジュールを python main.py から直接インポートできます。
特定の Python インタープリターを指定する場合は、次のように設定します。
cmake -S . -B build -DPython_EXECUTABLE="C:\Users\YourName\miniconda3\python.exe"プロジェクトのルートディレクトリで実行します。
cmake -S . -B build
cmake --build buildビルドが成功すると、build ディレクトリに次のようなファイルが生成されます。
fibonacci_cpp.cp313-win_amd64.pyd
ファイル名の Python バージョンタグは環境によって異なります。たとえば cp313 は CPython 3.13 を表します。
中心となる CMake 設定は次のとおりです。
find_package(Python REQUIRED COMPONENTS Interpreter Development.Module)
add_library(fibonacci_cpp MODULE
src/fibonacci.cpp
)
target_link_libraries(fibonacci_cpp PRIVATE Python::Module)生成されるモジュール名は fibonacci_cpp なので、Python では import fibonacci_cpp として読み込みます。
src/fibonacci.cpp は Python C API を使って次の関数を公開しています。
fibonacci_cpp.fibonacci(n)注意点:
nは 0 以上の整数である必要があります。- 戻り値は Python の
intなので、大きな整数にも対応できます。 - C++ 側では現在
nをunsigned long longとして解析しているため、受け付ける最大インデックスは18446744073709551615です。実際に計算できる大きさはメモリと実行時間にも依存します。
デモを実行します。
python main.pyより大きなベンチマークを実行します。
python main.py 1000000main.py は次の 2 つを行います。
fibonacci_cpp.fibonacci(0)からfibonacci_cpp.fibonacci(10)までの小さな例を表示します。- 同じ大きな
nに対して、純粋な Python 実装と C++ 拡張の Wall Time を比較します。
デフォルトのベンチマーク:
python main.py実行例:
Benchmark n = 100,000
Result decimal digits : 20,899
Python Wall Time : 0.052376 s
C++ Wall Time : 0.000816 s
Speedup : 64.18x
n = 1000000 の場合:
python main.py 1000000実行例:
Benchmark n = 1,000,000
Result decimal digits : 208,988
Python Wall Time : 4.540529 s
C++ Wall Time : 0.033997 s
Speedup : 133.56x
Wall Time はマシン、Python バージョン、コンパイラ、バックグラウンド負荷によって変わります。これらの数値は参考値です。より厳密に測定する場合は、複数回実行して平均を取るか、pyperf などの専用ツールを使ってください。
C++ 拡張は、計算量の多いホットパスに向いています。このプロジェクトでは次の点が効いています。
- Python 版は単純なループなので、各ステップで Python バイトコードの実行と変数束縛が発生します。
- C++ 拡張は重い計算部分をコンパイル済みモジュールへ移し、Python レベルのループオーバーヘッドを減らします。
- C++ 実装は高速倍加法を使い、通常の
O(n)反復ではなく、およそO(log n)回の大整数演算で Fibonacci を計算します。 - Python は呼び出し口と表示を担当し、C++ は重い計算を担当します。
すべての Python コードを C++ に移せば速くなるわけではありません。言語間呼び出しにもコストがあるため、この方法は計算量が多く、呼び出し回数が制御でき、ロジックが比較的安定している部分に向いています。
-
Python 公式チュートリアル: Extending and Embedding the Python Interpreter
https://docs.python.org/3/extending/ -
Python 公式リファレンス: Python/C API Reference Manual
https://docs.python.org/3/c-api/index.html -
Real Python チュートリアル: Building a Python C Extension Module
https://realpython.com/build-python-c-extension-module/ -
よりモダンな C++ ラッパーとして pybind11 も参考になります
https://pybind11.readthedocs.io/
