Выставление Eigen :: Tensor To Python Использование Pybind11 - PullRequest
0 голосов
/ 21 февраля 2020

Я пытаюсь выставить собственный тензор 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);
}

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

1 Ответ

1 голос
/ 01 марта 2020

Этот код C ++ не компилируется, и этот код python, возможно, не может быть запущен как опубликовано, но после исправления этих ошибок и внесения логических изменений все равно остается вывод, что pybind11 не поддерживает TensorMap из «неподдерживаемого / Eigen / CXX11». / Tensor ", поскольку этот класс не обеспечивает тот же интерфейс, что и другие классы отображения 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 не предоставляет свои размеры в столбцах / строках / шагах. Таким образом, SFINAE предотвращает автоматическое создание заклинателя c.

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

...