Eigen и Numpy -> Передача матриц из Python в C ++ - PullRequest
1 голос
/ 06 августа 2020

Я работаю над проектом моделирования и пытаюсь найти лучший способ передачи матриц между Python и C ++. Я использую Python s NumPy и библиотеку C ++ Eigen, а также PyBind11 , чтобы заставить их общаться друг с другом.

В моем коде (см. Ниже) , Я сначала создаю несколько массивов, используя NumPy в моем Python скрипте, а затем передаю их в качестве параметров функции конструктора класса C ++, который я называю rmodule, который, по сути, будет числовым движком моего моделирования. . Я хочу, чтобы экземпляр моего класса C ++ имел эти NumPy массивы в качестве атрибутов объекта (чтобы на них можно было легко ссылаться), но мне интересно, как лучше всего это сделать.

Если бы я просто выполнить преобразование типа из массива NumPy в матрицу Eigen, PyBind придется скопировать все эти данные в программу C ++. Хотя это кажется большим количеством накладных расходов, я чувствую, что это будет нормально, если копирование будет быстрым по сравнению с вычислениями, которые я делаю с матрицами.

Другой вариант - передать ссылку только на NumPy массивы в мой экземпляр C ++. Таким образом, данные не будут копироваться между Python и C ++ - они будут принадлежать Python и на них будет ссылаться класс C ++. Думаю, это может повысить производительность. Однако я не уверен, что при этом у меня возникнут проблемы - придется ли мне каким-то образом обходить GIL ? О чем еще мне следует помнить , если это лучший подход?

TL; DR: Я используя Python для файлового ввода-вывода и C ++ для вычислений. Должен ли я копировать данные между Python и C ++ или просто иметь данные, принадлежащие Python, и передавать ссылку на эти данные в C ++?

Любая помощь и совет приветствуются.

Код C ++:

#include <pybind11/pybind11.h>
#include <random>
#include <iostream>
#include "Eigen/Dense"

#define R = 8.134 // Universal Gas Constant (J mol^-1 ºK^-1)

namespace py = pybind11;

using namespace Eigen;

class rmodule {
    /** Encapsulated time-stepping logic that
        can be easily constructed and referenced
        by the Python interpreter.

        :attributes:
            C   - Concentration Vector
            F   - Standard ΔGº_f of metabolites
            T   - Temperature (ºK)
            S   - Stoichiometric Matrix
         */

    VectorXf C;
    VectorXf F;
    double   T = 0.0;
    MatrixXf S;

public:
    rmodule(VectorXf pyC, MatrixXf pyS, VectorXf pyF, double pyT) {
       /** Copies numpy array data into C++ Eigen classes. */
        C   = pyC;
        S   = pyS;
        F   = pyF;
        T   = pyT;
    }

    ~rmodule(){     // TODO -- Will need to free data structures
        ;
    }
};

PYBIND11_MODULE(reaction, m) {
    m.doc() = "ERT reaction module";    // TODO -- How to bind?

    py::class_<rmodule>(m, "rmodule")
        .def(py::init<>()) // Here is the Problem! What should I do here? Reference or value?
        ;
}

Python Код:

import parser
import react   # react is the name of my binary once I compile
import numpy as np

def main():
    """Program Driver"""

    P = parser.Parser("test1.txt")
    P.ReadData() # Builds numpy arrays

    C = P.GetC()    # Initial Concentrations #
    S = P.GetS()    # Stoichiometric Matrix #
    F = P.GetF()    # Standard ΔGº #

    rmodule = react.rmodule(C, S, F, T=273.15)


if __name__ == "__main__":
    main()

1 Ответ

3 голосов
/ 06 августа 2020

Придумал компромисс! Я собираюсь скопировать значения из Python в C ++ один раз, а затем просто вставить ссылки на данные из C ++ в Python.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...