Eigen 和 Numpy -> 将矩阵从 Python 传递给 C++

Eigen and Numpy -> Passing Matrices from Python to C++

我正在做一个模拟项目,我正在尝试找出在 Python 和 C++ 之间传递矩阵的最佳方法。我正在使用 Python 的 NumPy 和 C++ 的 Eigen 库,并且我正在使用 PyBind11 让它们相互通信。

在我的代码中(见下文),我首先在 Python 脚本中使用 NumPy 创建一些数组,然后将这些作为参数传递给 C++ class 的构造函数,我调用rmodule,这实际上将成为我模拟的数值引擎。我想要我的 C++ class 的一个实例将这些 NumPy 数组作为对象属性(这样它们可以很容易地被引用),但我想知道最好的方法是什么。

如果我只是进行从 NumPy 数组到 Eigen 矩阵的类型转换,PyBind 将不得不将所有数据复制到 C++ 程序。虽然这看起来开销很大,但我觉得如果与我对矩阵进行的计算相比复制速度更快的话,这样就可以了。

我的另一个选择是只将对 NumPy 数组的引用传递到我的 C++ 实例。这样一来,数据就不会在 Python 和 C++ 之间来回复制——数据将由 Python 拥有并由 C++ class 引用。我认为这可能会提高性能。但是,我不确定这样做是否会 运行 遇到麻烦 - 我是否必须以某种方式解决 GIL 问题?我还应该记住哪些其他事项如果这是更好的方法?

TLDR: 我使用 Python 文件 I/O 和 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()

想出了一个折衷方案!我打算将值从 Python 复制到 C++ 一次,然后将对数据的引用从 C++ 复制到 Python.