[PYTHON] Erweitern Sie NumPy mit Rust

Vorteile von Python

Probleme mit Python


Bemühungen um Beschleunigung


Python-Erweiterungen und NumPy-Erweiterungen

Sie müssen beide C-APIs verwenden


In welcher Sprache erweitern Sie NumPy?


Warum Rost?

--Rust ist eine moderne Systemsprache, die für numerische Berechnungen geeignet ist (glaube ich). --Borrow Checker eliminiert Datenrennen --C ++ - wie Speichermodell-Verschiebungssemantik (kein GC)


rust-cpython

https://github.com/dgrunwald/rust-cpython


Rufen Sie Python von Rust aus auf

extern crate cpython;

use cpython::{Python, PyDict, PyResult};

fn main() {
    let gil = Python::acquire_gil();
    hello(gil.python()).unwrap();
}

fn hello(py: Python) -> PyResult<()> {
    let sys = py.import("sys")?;
    let version: String = sys.get(py, "version")?.extract(py)?;

    let locals = PyDict::new(py);
    locals.set_item(py, "os", py.import("os")?)?;
    let user: String = py.eval("os.getenv('USER') or os.getenv('USERNAME')", None, Some(&locals))?.extract(py)?;

    println!("Hello {}, I'm Python {}", user, version);
    Ok(())
}

Aufrufen von Rust-Funktionen aus Python

#[macro_use] extern crate cpython;

use cpython::{PyResult, Python};

// add bindings to the generated python module
// N.B: names: "librust2py" must be the name of the `.so` or `.pyd` file
py_module_initializer!(librust2py, initlibrust2py, PyInit_librust2py, |py, m| {
    try!(m.add(py, "__doc__", "This module is implemented in Rust."));
    try!(m.add(py, "sum_as_string", py_fn!(py, sum_as_string_py(a: i64, b:i64))));
    Ok(())
});

// logic implemented as a normal rust function
fn sum_as_string(a:i64, b:i64) -> String {
    format!("{}", a + b).to_string()
}

// rust-cpython aware function. All of our python interface could be
// declared in a separate module.
// Note that the py_fn!() macro automatically converts the arguments from
// Python objects to Rust values; and the Rust return value back into a Python object.
fn sum_as_string_py(_: Python, a:i64, b:i64) -> PyResult<String> {
    let out = sum_as_string(a, b);
    Ok(out)
}

rust-numpy

https://github.com/termoshtt/rust-numpy


rust-ndarray

https://github.com/bluss/rust-ndarray

extern crate ndarray;
use ndarray::*;

// immutable example
fn axpy(a: f64, x: ArrayViewD<f64>, y: ArrayViewD<f64>) -> ArrayD<f64> {
    a * &x + &y
}

// mutable example (no return)
fn mult(a: f64, mut x: ArrayViewMutD<f64>) {
    x *= a;
}

rust-numpy

#[macro_use]
extern crate cpython;
extern crate numpy;

use numpy::*;
use cpython::{PyResult, Python, PyObject};

// wrapper of `axpy`
fn axpy_py(py: Python, a: f64, x: PyArray, y: PyArray) -> PyResult<PyArray> {
    let np = PyArrayModule::import(py)?;
    let x = x.as_array().into_pyresult(py, "x must be f64 array")?;
    let y = y.as_array().into_pyresult(py, "y must be f64 array")?;
    Ok(axpy(a, x, y).into_pyarray(py, &np))
}

// wrapper of `mult`
fn mult_py(py: Python, a: f64, x: PyArray) -> PyResult<PyObject> {
    let x = x.as_array_mut().into_pyresult(py, "x must be f64 array")?;
    mult(a, x);
    Ok(py.None()) // Python function must returns
}

/* Define module "_rust_ext" */
py_module_initializer!(_rust_ext, init_rust_ext, PyInit__rust_ext, |py, m| {
    m.add(py, "__doc__", "Rust extension for NumPy")?;
    m.add(py, "axpy", py_fn!(py, axpy_py(a: f64, x: PyArray, y: PyArray)))?;
    m.add(py, "mult", py_fn!(py, mult_py(a: f64, x: PyArray)))?;
    Ok(())
});

setuptools-rust

--rust-c Eine Bibliothek zum Behandeln von Python-Erweiterungen mit Setuptools

setup.py
extensions/Cargo.toml
           src/lib.rs
rust_ext/__init__.py

setup.py


from setuptools import setup
from setuptools_rust import RustExtension

setup(name='rust_ext',
      version='1.0',
      rust_extensions=[
          RustExtension('rust_ext._rust_ext', 'extensions/Cargo.toml')],
      packages=['rust_ext'],
      zip_safe=False)

rust_ext/__init__.py


from ._rust_ext import *

Nennen Sie Rost-Numpy

python setup.py install
import rust_ext
import numpy as np

x = np.array([1.0, 2.0])
y = np.array([2.0, 3.0])
rust_ext.axpy(3, x, y)

(* '▽') Es hat funktioniert!


Endlich: Wenn Rost schmerzhaft ist

Recommended Posts

Erweitern Sie NumPy mit Rust
Gleitender Durchschnitt mit Numpy
[Rust / Python] Behandle Numpy mit PyO3 (Version August 2020)
Erste Schritte mit Numpy
Verkettung von Matrizen mit Numpy
Summencode mit Numpy
Führen Sie eine Regressionsanalyse mit NumPy durch
Kernel-Regression nur mit Numpy
Ich habe GP mit Numpy geschrieben
CNN-Implementierung mit nur Numpy
Künstliche Datengenerierung mit Numpy
Versuchen Sie die Matrixoperation mit NumPy
Animation der Diffusionsgleichung mit NumPy
Schuldenrückzahlungssimulation mit Numpy
SMO mit Python + NumPy implementiert
Kleben Sie die Saiten mit Numpy zusammen
Behandle numpy Arrays mit f2py
Verwenden Sie OpenBLAS mit numpy, scipy
Implementierung der logistischen Regression mit NumPy
Verwenden Sie Python-ähnliche Bereiche mit Rust
Führen Sie eine minimale quadratische Anpassung mit numpy durch.
Zeichne einen schönen Kreis mit Numpy
Implementieren Sie Keras LSTM Feed Forward mit Numpy
Extrahieren Sie mehrere Elemente mit dem Numpy-Array
Lesen und Schreiben von CSV-Dateien mit Numpy
Erstellen Sie bin mit NumPy, erhalten Sie die Korrespondenz zwischen Daten und bin
Zeichnen Sie Dreiecksfunktionen mit Numpy und Matplotlib
Ich habe ein Lebensspiel mit Numpy gemacht
Zeichendatendatei mit numpy lesen
Behandle numpy mit Cython (Methode von memoryview)
Verwenden Sie BLAS / LAPACK mit mehreren Threads mit numpy / scipy