使用 Pybind11 将 Eigen::Tensor 公开给 Python
Exposing Eigen::Tensor To Python Using Pybind11
我正在尝试使用 pybind11 将特征张量公开给 python。我可以毫无问题地编译所有内容,并将其成功导入 python。但是,数据无法转换为 python 类型。我尝试了两种方法。一种是直接公开数据,第二种是使用映射。两者都在 python 环境中失败。
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/stl_bind.h>
#include <pybind11/numpy.h>
#include <pybind11/eigen.h>
#include <unsupported/Eigen/CXX11/Tensor>
class myclass{
myclass(){
m_data = new float[m_dim1*m_dim2*m_dim3]; // Contiguous data that represents a three dimensional array
for(int i = 0; i<m_dim1*m_dim2*m_dim3; i++)
m_data[i] = i;
m_tensor = Eigen::TensorMap<Eigen::Tensor<float, 3>>(m_data, m_dim1, m_dim2, m_dim3);
}
Eigen::TensorMap<Eigen::Tensor<float, 3>>& getDataUsingMapping() { Eigen::TensorMap<Eigen::Tensor<float, 3>> temp(m_data, m_dim1, m_dim2, m_dim3); return temp; }
Eigen::Tensor<float, 3>& getDataWithoutUsingMapping() { return m_tensor};
private:
Eigen::Tensor<float, 3> m_tensor;
// In fact, m_data, m_dim1, m_dim2, m_dim3 all are
// read from a data file but for this example let's
// assume some values.
float* m_data;
int m_dim1 = 2, m_dim2 = 5, m_dim3 = 10;
}
PYBIND11_MODULE(example, m) {
py::class_<myclass>(m, "myclass")
.def(py::init<>())
.def("getDataUsingMapping", &myClass::getDataUsingMapping, py::return_value_policy::reference)
.def("getDataWithoutUsingMapping", &myClass::getDataWithoutUsingMapping, py::return_value_policy::reference);
}
我希望能够使用其维度信息 (m_dim1, m_dim2, m_dim3)
在 python 中处理这个 3D 数组。
这是我在尝试获取 python 中的数据后收到的错误消息。
>>> import example
>>> d = example()
>>>
>>> DataInPython = d.getDataUsingMapping()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Unable to convert function return value to a Python type! The signature was
(self: example) -> Eigen::TensorMap<Eigen::Tensor<float,3,0,__int64>,0,Eigen::MakePointer>
>>>
>>>
>>> DataInPython = d.getDataWithoutUsingMapping()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Unable to convert function return value to a Python type! The signature was
(self: example) -> Eigen::Tensor<std::complex<float>,3,0,__int64>
Did you forget to `#include <pybind11/stl.h>`? Or <pybind11/complex.h>,
<pybind11/functional.h>, <pybind11/chrono.h>, etc. Some automatic
conversions are optional and require extra headers to be included
when compiling your pybind11 module.
我尝试包含所有 pybdin11 包含文件,但没有解决问题。有人可以帮助我吗?
C++ 代码无法编译,python 代码不可能有发布的 运行,但在修复这些问题并进行逻辑更改后,结论仍然是 pybind11 不支持来自 "unsupported/Eigen/CXX11/Tensor" 的 TensorMap,因为 class 不提供与其他 Eigen 映射 classes.
相同的接口
我原以为 mapper caster 的专业化会自动工作,但这样做是明确的:
template<>
struct py::detail::type_caster<Eigen::TensorMap<Eigen::Tensor<float, 3>>, void>
: py::detail::eigen_map_caster<Eigen::TensorMap<Eigen::Tensor<float, 3>>> {};
pybind11::detail::EigenProps 的实例化失败,b/c TensorMap 不提供 cols/rows/stride 的维度。因此,SFINAE 阻止自动生成脚轮。
除了使用名为 "unsupported" 的目录中的 headers 之外,没有其他选择吗?如果没有,最好的办法是将 TensorMap 的内容复制到一个 numpy 数组,然后复制到 return getDataUsingMapping
的自定义:有几个示例说明如何在 SO 上执行此操作,有和没有复制. (除非您愿意展平张量,否则 EigenProps 的特化将不起作用,但您可以将其用作示例来为 TensorMap 编写新的通用类型施法器。)
我正在尝试使用 pybind11 将特征张量公开给 python。我可以毫无问题地编译所有内容,并将其成功导入 python。但是,数据无法转换为 python 类型。我尝试了两种方法。一种是直接公开数据,第二种是使用映射。两者都在 python 环境中失败。
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/stl_bind.h>
#include <pybind11/numpy.h>
#include <pybind11/eigen.h>
#include <unsupported/Eigen/CXX11/Tensor>
class myclass{
myclass(){
m_data = new float[m_dim1*m_dim2*m_dim3]; // Contiguous data that represents a three dimensional array
for(int i = 0; i<m_dim1*m_dim2*m_dim3; i++)
m_data[i] = i;
m_tensor = Eigen::TensorMap<Eigen::Tensor<float, 3>>(m_data, m_dim1, m_dim2, m_dim3);
}
Eigen::TensorMap<Eigen::Tensor<float, 3>>& getDataUsingMapping() { Eigen::TensorMap<Eigen::Tensor<float, 3>> temp(m_data, m_dim1, m_dim2, m_dim3); return temp; }
Eigen::Tensor<float, 3>& getDataWithoutUsingMapping() { return m_tensor};
private:
Eigen::Tensor<float, 3> m_tensor;
// In fact, m_data, m_dim1, m_dim2, m_dim3 all are
// read from a data file but for this example let's
// assume some values.
float* m_data;
int m_dim1 = 2, m_dim2 = 5, m_dim3 = 10;
}
PYBIND11_MODULE(example, m) {
py::class_<myclass>(m, "myclass")
.def(py::init<>())
.def("getDataUsingMapping", &myClass::getDataUsingMapping, py::return_value_policy::reference)
.def("getDataWithoutUsingMapping", &myClass::getDataWithoutUsingMapping, py::return_value_policy::reference);
}
我希望能够使用其维度信息 (m_dim1, m_dim2, m_dim3)
在 python 中处理这个 3D 数组。
这是我在尝试获取 python 中的数据后收到的错误消息。
>>> import example
>>> d = example()
>>>
>>> DataInPython = d.getDataUsingMapping()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Unable to convert function return value to a Python type! The signature was
(self: example) -> Eigen::TensorMap<Eigen::Tensor<float,3,0,__int64>,0,Eigen::MakePointer>
>>>
>>>
>>> DataInPython = d.getDataWithoutUsingMapping()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Unable to convert function return value to a Python type! The signature was
(self: example) -> Eigen::Tensor<std::complex<float>,3,0,__int64>
Did you forget to `#include <pybind11/stl.h>`? Or <pybind11/complex.h>,
<pybind11/functional.h>, <pybind11/chrono.h>, etc. Some automatic
conversions are optional and require extra headers to be included
when compiling your pybind11 module.
我尝试包含所有 pybdin11 包含文件,但没有解决问题。有人可以帮助我吗?
C++ 代码无法编译,python 代码不可能有发布的 运行,但在修复这些问题并进行逻辑更改后,结论仍然是 pybind11 不支持来自 "unsupported/Eigen/CXX11/Tensor" 的 TensorMap,因为 class 不提供与其他 Eigen 映射 classes.
相同的接口我原以为 mapper caster 的专业化会自动工作,但这样做是明确的:
template<>
struct py::detail::type_caster<Eigen::TensorMap<Eigen::Tensor<float, 3>>, void>
: py::detail::eigen_map_caster<Eigen::TensorMap<Eigen::Tensor<float, 3>>> {};
pybind11::detail::EigenProps 的实例化失败,b/c TensorMap 不提供 cols/rows/stride 的维度。因此,SFINAE 阻止自动生成脚轮。
除了使用名为 "unsupported" 的目录中的 headers 之外,没有其他选择吗?如果没有,最好的办法是将 TensorMap 的内容复制到一个 numpy 数组,然后复制到 return getDataUsingMapping
的自定义:有几个示例说明如何在 SO 上执行此操作,有和没有复制. (除非您愿意展平张量,否则 EigenProps 的特化将不起作用,但您可以将其用作示例来为 TensorMap 编写新的通用类型施法器。)