Boost.NumPy Tutorial zum Erweitern von Python in C ++ (Übung)

C ++ Adventskalender Tag 10 Artikel.

Boost.NumPy wird in Boost 1.63 mit Boost.Python zusammengeführt. Gleichzeitig kann ein Problem mit der folgenden Beschreibung auftreten. Ich werde einen überarbeiteten Artikel schreiben.

Motivation

Python ist wirklich praktisch. Für mich ist das eine Akademie (Lehrling), deren Schwerpunkt auf der Simulation und Analyse der Ergebnisse liegt. Ein IPython-Notizbuch, mit dem Sie Daten nahtlos interaktiv verarbeiten, analysieren und visualisieren können, ist ein Muss. Leider bietet C ++ allein (wahrscheinlich) nicht die entsprechende Funktionalität. Das von CERN erstellte Festhalten an ROOT scheint in der Lage zu sein, C ++ interaktiv auszuführen, aber ich habe es nie verwendet, da es nur wenige Informationen gibt. Bitte erstellen Sie ein IC ++ - Notizbuch, das jemand (dringend) in C ++ programmieren kann.

Die Simulation selbst läuft jedoch Tage bis Wochen, Geschwindigkeit ist wichtig und Python kann nicht in einer langsamen Sprache geschrieben werden. Die Simulation wird also in C ++ geschrieben (was ist Fortran so lecker).

Auf der anderen Seite sind Projekte wie scikit-learn und PyMC Frontends für Python. Wenn Sie sich den Ort ansehen, an dem Ich bin der Meinung, dass es vorerst üblicher wird, es in einer anderen Sprache zu implementieren und von Python aus zu verwenden. Also unter den Methoden zum Schreiben von Funktionen, die in Python in C ++ verwendet werden können So verwenden Sie Boost.NumPy.

Warum Boost.NumPy?

Ich habe einmal versucht, Boost.Python zu verwenden und war frustriert, weil der Konverter nicht verstanden hat Boost.NumPy war sehr einfach zu bedienen (wichtig).

Um die anderen Optionen kurz zu erwähnen: Boost.NumPy, das dieses Mal eingeführt wurde, verwendet einfach die Methode zum Erstellen des C ++ - Wrappings von Pythons numpy.ndarray. Da C ++ bereits (unzählige) Bibliotheken hat, die lineare algebraische Operationen wie Eigen ausführen Es gibt auch eine Auswahl, die numpy.ndarray unverändert in den mehrdimensionalen Eigenvektor konvertiert. Einfacher, wenn Sie nur Boost.Python verwenden, konvertieren Sie C ++ vector etc. in eine Python-Liste. Sie haben auch die Möglichkeit, dann in "numpy.ndarray" zu konvertieren. Es gibt viele andere wie SWIG und Cython.

Zweck

Ich habe in Vorheriger Artikel zusammengefasst, wie es installiert und kompiliert wird. Dieses Mal werde ich zusammenfassen, wie es tatsächlich verwendet wird. Normalerweise möchte ich also nur den Schnittstellenteil von C ++ - Code von der Python-Seite verwenden Ich werde zusammenfassen, wie man es so einfach wie möglich benutzt und dabei schwierige Dinge vermeidet.

Ich werde Boost.Python nicht erklären, also überprüfen Sie es bitte selbst. Unten finden Sie eine Liste der Boost.Python-Kommentarseiten:

Tutorial for Boost.NumPy

Folgendes habe ich basierend auf dem Boost.NumPy-Tutorial geschrieben. Um die Komplexität der Notation zu beseitigen, wird der Namespace wie folgt abgekürzt.

namespace p = boost::python;
namespace np = boost::numpy;

Wie man np :: ndarray benutzt (für eindimensional)

Die Einführung war lang, also fügen wir einen Code ein, der schnell funktioniert:

mymod1.cpp


#include "boost/numpy.hpp"
#include <stdexcept>
#include <algorithm>

namespace p = boost::python;
namespace np = boost::numpy;

/*Doppelt*/
void mult_two(np::ndarray a) {
  int nd = a.get_nd();
  if (nd != 1)
    throw std::runtime_error("a must be 1-dimensional");
  size_t N = a.shape(0);
  if (a.get_dtype() != np::dtype::get_builtin<double>())
    throw std::runtime_error("a must be float64 array");
  double *p = reinterpret_cast<double *>(a.get_data());
  std::transform(p, p + N, p, [](doublex){return2*x;});
}

BOOST_PYTHON_MODULE(mymod1) {
  Py_Initialize();
  np::initialize();
  p::def("mult_two", mult_two);
}

Dies kann so wie es ist kompiliert werden. Es ist eine einfache Funktion, die ein eindimensionales Array nur verdoppelt, aber wichtige Elemente enthält.

--Verwenden Sie get_nd () für Array-Dimensionen

Der Speicher wird auf der Seite "np :: ndarray" verwaltet, sodass Sie sich dessen nicht bewusst sein müssen. Leider wird der Typ dynamisch bestimmt, sodass die Funktion nicht überladen werden kann. Es muss nach der if-Anweisung zum Zeitpunkt der Ausführung beurteilt werden. Es ist schön, Ausnahmen zu konvertieren.

Beginnen wir mit Python.

mymod1.py


#!/usr/bin/env python
# -*- coding: utf-8 -*-

import mymod1
import numpy as np

if __name__ == '__main__':
    a = np.array([1,2,3], dtype=np.float64)
    mymod1.mult_two(a)
    print(a)

    b = np.array([1,2,3], dtype=np.int64)
    mymod1.mult_two(b) # raise error
    print(b)

Der b-Teil ist ein Fehler, da der Typ "long long" anstelle von "double" ist, wie oben beschrieben:

[ 2.  4.  6.]
Traceback (most recent call last):
  File "/path/of/mymod1.py", line 13, in <module>
    mymod1.mult_two(b)
RuntimeError: a must be float64 array

Wenn Sie eine Ganzzahl für numpy verwenden, wird "int64" ("long long" in C ++) verwendet, sofern nicht anders angegeben. Bitte beachten Sie, dass es nicht "int" ist.

Es gibt einige Beschwerden wie nicht überladen zu können, Ich konnte eine Funktion implementieren, die in Python in C ++ leicht verwendet werden kann.

Verwendung von np :: ndarray (für mehrdimensionale)

Die Grundlagen sind für mehrdimensionale Dateien gleich, Sie müssen jedoch auf die Reihenfolge des Speichers achten. Die Erklärung von numpy.ndarray.stride ist leicht zu verstehen, aber unten Ich werde es kurz erklären.

Manchmal möchten Sie ein zweidimensionales Array in einem kontinuierlichen Speicherbereich verwalten.

double *a_as1 = new double[N*M];
double **a_as2 = new double*[N];
for(int i=0;i<N;++i){
  a_as2[i] = &a_as1[i*M];
}

Auf diese Weise ist der von "a_as2 [i] [j]" aufgerufene Speicher derselbe wie "a_as1 [i * M + j]". Die Art und Weise, so etwas zu tun, ist "ndarray.stride". In diesem Fall rückt es im Speicher um 8 Bytes vor, um 1 in j-Richtung vorzurücken (double ist 8 Bytes). Um andererseits 1 in die i-Richtung vorzurücken, wird "8 * M" Byte im Speicher vorgerückt ("(i + 1) * M + j = i * M + j + M"). Diese "8" und "8 * M" werden Schritt (Schritt) genannt. Diese Idee kann auch in höheren Dimensionen verwendet werden.

Wenn Sie darauf achten, ist der Rest einfach.

#include "boost/numpy.hpp"
#include <iostream>
#include <stdexcept>
#include <algorithm>

namespace p = boost::python;
namespace np = boost::numpy;

void print(np::ndarray a) {
  int nd = a.get_nd();
  if (nd != 2)
    throw std::runtime_error("a must be two-dimensional");
  if (a.get_dtype() != np::dtype::get_builtin<double>())
    throw std::runtime_error("a must be float64 array");

  auto shape = a.get_shape();
  auto strides = a.get_strides();

  std::cout << "i j val\n";
  for (int i = 0; i < shape[0]; ++i) {
    for (int j = 0; j < shape[1]; ++j) {
      std::cout << i << " " << j << " "
                << *reinterpret_cast<double *>(a.get_data() + i * strides[0] +
                                               j * strides[1]) << std::endl;
    }
  }
}

BOOST_PYTHON_MODULE(mymod2) {
  Py_Initialize();
  np::initialize();
  p::def("print", print);
}

Es ist schneller, den Schritt zu betrachten und ihn in aufsteigender Reihenfolge in Bezug auf den Speicherzugriff zu drehen. Ich habe es weggelassen, weil es problematisch ist. Bitte gib dein bestes.

Schließlich

Python oder NumPy ist sehr praktisch. Höchstwahrscheinlich bietet SciPy eine Standardschnittstelle für Mathematikbibliotheken mit gut dokumentierten.

Nachdem wir nun zusammengefasst haben, wie auf die Daten in np :: ndarray zugegriffen werden kann, Ich denke, dass der in C ++ implementierte Algorithmus von Python aus verwendet werden kann. Als nächstes möchte ich mich über Beiträge zu PyPI und Beiträge zu scikits informieren.

Recommended Posts

Boost.NumPy Tutorial zum Erweitern von Python in C ++ (Übung)
Erweitern Sie Python in C ++ (Boost.NumPy)
Weiter Python in C-Sprache
C-API in Python 3
Techniken zum Sortieren in Python
Binäre Suche in Python / C ++
Einführung in Python in der Praxis (PiP)
Über "für _ in range ():" von Python
Newtons Methode in C ++, Python, Go (zum Verständnis von Funktionsobjekten)
Gehirnwellenanalyse mit Python: Python MNE-Tutorial
Überprüfen Sie Python auf Speicherlecks
Suchen Sie mit Python nach externen Befehlen
ABC166 in Python A ~ C Problem
Python-Spickzettel (für C ++ erfahren)
Löse ABC036 A ~ C mit Python
Tipps zum Aufrufen von Python von C.
So verpacken Sie C in Python
Algorithmus (Segmentbaum) in Python (Übung)
Führen Sie unittest in Python aus (für Anfänger)
Löse ABC037 A ~ C mit Python
Schreiben Sie einen C-Sprach-Unit-Test in Python
Lernverlauf für die Teilnahme an der Team-App-Entwicklung mit Python ~ Django Tutorial 5 ~
Lernverlauf für die Teilnahme an der Entwicklung von Team-Apps mit Python ~ Django Tutorial 4 ~
Lernverlauf für die Teilnahme an der Team-App-Entwicklung mit Python ~ Django Tutorial 1, 2, 3 ~
Best Practice für die Anmeldung im JSON-Format unter AWS Lambda / Python
Lernverlauf für die Teilnahme an der Team-App-Entwicklung mit Python ~ Django Tutorial 6 ~
Lernverlauf für die Teilnahme an der Team-App-Entwicklung mit Python ~ Django Tutorial 7 ~
Löse ABC175 A, B, C mit Python
Anmerkung von nfc.ContactlessFrontend () von nfcpy von Python
Algorithmus in Python (ABC 146 C Dichotomie
Implementieren Sie den FIR-Filter in Python und C.
Tipps zum Umgang mit Binärdateien in Python
Zusammenfassung verschiedener for-Anweisungen in Python
Geben Sie Anmerkungen für Python2 in Stub-Dateien ein!
Python-Tutorial
Schreiben Sie die O_SYNC-Datei in C und Python
Vorlage zum Schreiben von Batch-Skripten in Python
Verarbeiten Sie mehrere Listen mit for in Python
MongoDB mit Python zum ersten Mal
Holen Sie sich ein Zeichen für Conoha mit Python
Beispiel für den Umgang mit EML-Dateien in Python
AtCoder Spickzettel in Python (für mich)
Ich habe mit Python nach einer Primzahl gesucht
Hinweise zur Verwendung von Python (Pydev) mit Eclipse
Generieren Sie mit Python eine C-Sprache aus dem S-Ausdruck
Tipps zum Erstellen kleiner Werkzeuge mit Python
Verwenden Sie pathlib in Maya (Python2.7), um sich auf das kommende Python3.7 vorzubereiten
Führen Sie Python in C ++ unter Visual Studio 2017 aus
Eine Einführung in Python für C-Sprachprogrammierer
Stellen Sie die von Eigen of C ++ erstellte Bibliothek mit Boost.Numpy in Python zur Verfügung.
Geben Sie Notizen zu Python-Skripten ein, um das PyTorch-Modell in C ++ mit libtorch auszuführen
Vorlage zum Erstellen von Befehlszeilenanwendungen in Python
[Python, Scala] Machen Sie ein Tutorial für Apache Spark
Verwendung der C-Bibliothek in Python
CERTIFICATE_VERIFY_FAILED in Python 3.6, dem offiziellen Installationsprogramm für macOS
Verwenden Sie Python für formatierte Ausgaben wie C / C ++ printf
++ und-können nicht zum Inkrementieren / Dekrementieren in Python verwendet werden
So generieren Sie eine Sequenz in Python und C ++
Führen Sie Python YOLOv3 in C ++ unter Visual Studio 2017 aus