Python インタープリターの根底にある原則についていくつか質問したいと思います。私自身の検索ではあまり有用な情報が得られなかったからです。
私は最近、python プラグインを書くために錆を使用しています。これにより、python の CPU 集約型タスクが大幅に高速化され、c と比較して書き込みも高速になります。ただし、cython を使用して高速化する古いスキームと比較して、1 つの欠点があります。rust の呼び出しオーバーヘッド (私は pyo3 を使用しています) は、c (私は cython を使用しています) の呼び出しオーバーヘッドよりも大きいようです。
たとえば、ここに空の python 関数があります。
def empty_function():
return 0
Python で for ループを介して 100 万回呼び出して時間を数えると、1 回の呼び出しに約 70 ナノ秒かかることがわかります (私の PC では)。
同じソースコードで cython プラグインにコンパイルすると、次のようになります。
# test.pyx
cpdef unsigned int empty_function():
return 0
実行時間は 40 ナノ秒に短縮されます。つまり、cython を使用して細かい埋め込みを行うことができ、常にネイティブの python よりも高速に実行されることが期待できます。
ただし、Rust に関しては (正直なところ、プラグイン開発には cython よりもむしろ ruby を使用する方が好きです。これは、文法で奇妙なハッキングを行う必要がないためです)、呼び出し時間は 140 ナノ秒に増加し、ほぼ 2 倍になります。ネイティブのパイソン。ソースコードは次のとおりです。
use pyo3::prelude::*;
use pyo3::wrap_pyfunction;
#[pyfunction]
fn empty_function() -> usize {
0
}
#[pymodule]
fn testlib(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(empty_function, m)?)?;
Ok(())
}
これは、さびが python のきめの細かい埋め込み置換には適していないことを意味します。呼び出し時間が非常に少なく、各呼び出しに時間がかかるタスクがある場合は、rust を使用するのが最適です。ただし、コード内で頻繁に呼び出されるタスクがある場合、型変換のオーバーヘッドが加速時間のほとんどを占めるため、rust には適していないようです。
これが解決できるかどうかを知りたいのですが、さらに重要なことに、この不一致の根底にある理論的根拠を知りたいのです。cプラグインを呼び出すときのcpythonとpypyの違いのように、それらの間で呼び出すときにcpythonインタープリターと何らかの違いがありますか? 詳細情報はどこで入手できますか? ありがとう。
===
アップデート:
申し訳ありませんが、私の質問があいまいになるとは思っていませんでした。結局のところ、3 つすべてのソース コードが提供されており、timeit を使用して関数ランタイムをテストすることは、Python 開発のほとんどの慣習です。
私のテスト コードは、@Jmb のコメントのコードとほとんど同じですpython setup.py build_ext --inplace
が、ベア gcc の代わりにビルドする方法を使用しているという微妙な違いがありますが、違いはありません。とにかく、補足ありがとう。