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.
我正在做一个模拟项目,我正在尝试找出在 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.