Предоставление Eigen :: Tensor Python с помощью Pybind11

Я пытаюсь предоставить тензор Eigen для python с помощью pybind11. Я могу скомпилировать все без проблем и успешно импортировать это в 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);
}

Я хотел бы иметь возможность обрабатывать этот 3D-массив на Python с его размерной информацией (m_dim1, m_dim2, m_dim3).

Вот сообщения об ошибках, которые я получаю после попытки получить данные в 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, но не решил проблему. Может ли кто-нибудь помочь мне?


person AFPP    schedule 21.02.2020    source источник
comment
У вас есть ошибка при преобразовании сложного числа с плавающей запятой, я предполагаю, что complex.h не был включен, даже когда вы пытались. Не могли бы вы объяснить, как вы включили все эти модули (complex.h functional.h chrono.h)?   -  person Christian    schedule 28.02.2020


Ответы (1)


Этот код C ++ не компилируется и этот код python не может быть запущен так, как было опубликовано, но после их исправления и внесения логических изменений можно сделать вывод, что pybind11 не поддерживает TensorMap из "unsupported / Eigen / CXX11 / Tensor" как это class не предоставляет тот же интерфейс, что и другие классы сопоставления Eigen.

Я ожидал, что специализация 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 предотвращает автоматическую генерацию заклинателя.

Есть ли другой вариант, кроме использования заголовков из каталога с именем "неподдерживаемый"? Если нет, лучше всего скопировать содержимое TensorMap в массив numpy и вернуть его в настройке getDataUsingMapping: есть несколько примеров того, как это сделать на SO, с копированием и без него. (Специализация EigenProps не будет работать, если вы не захотите сгладить тензор, но вы можете использовать ее в качестве примера для написания нового универсального передатчика типа для TensorMap.)

person Wim Lavrijsen    schedule 01.03.2020
comment
Мое знание pybind11 связано с вами. Спасибо, что нашли время в своем плотном графике и помогли сообществу. - person AFPP; 02.03.2020