Модуль C ++ Python вылетает в Blender, но не в консоли Python - PullRequest
1 голос
/ 19 июня 2020

Проблема

Я пытаюсь вызвать свой код C ++ из Python 3.7 с помощью Blender 2.82a (также происходит в 2.83). Код должен оптимизировать путь камеры. Его можно использовать без Blender, однако я использую Blender для настройки сцены с указанием пути камеры и значений глубины запроса в сцене.

Я пробовал вызвать функцию оптимизации в C ++ и в консоли Python. Оба работали без проблем. Проблема в том, что когда я вызываю его в Blender, Blender вылетает.

Это cra sh отчет :

# Blender 2.83.0, Commit date: 2020-06-03 14:38, Hash 211b6c29f771

# backtrace
./blender(BLI_system_backtrace+0x1d) [0x6989e9d]
./blender() [0xc1548f]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x153c0) [0x7fa5fb3dc3c0]
/lib/x86_64-linux-gnu/libpthread.so.0(raise+0xcb) [0x7fa5fb3dc24b]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x153c0) [0x7fa5fb3dc3c0]
./blender(_ZN5Eigen8IOFormatD1Ev+0xa3) [0x179bc43]
/home/name/Programs/blender-2.83.0-linux64/2.83/python/lib/python3.7/optFlowCam.cpython-37m-x86_64-linux-gnu.so(_Z2_zRK6CameraRKN5Eigen6MatrixIdLi9ELi1ELi0ELi9ELi1EEEiiRKSt8functionIFdRK3RayEE+0x2e2) [0x7fa5d1538e72]
/home/name/Programs/blender-2.83.0-linux64/2.83/python/lib/python3.7/optFlowCam.cpython-37m-x86_64-linux-gnu.so(_ZN11OpticalFlow13GradPathErrorERKSt6vectorI6CameraSaIS1_EEiiRKSt8functionIFdRK3RayEEd+0x5a7) [0x7fa5d1539c77]
/home/name/Programs/blender-2.83.0-linux64/2.83/python/lib/python3.7/optFlowCam.cpython-37m-x86_64-linux-gnu.so(_Z16_gradientDescentRKSt6vectorI6CameraSaIS0_EEiiRKSt8functionIFdRK3RayEEd+0x54b) [0x7fa5d153b5fb]
/home/name/Programs/blender-2.83.0-linux64/2.83/python/lib/python3.7/optFlowCam.cpython-37m-x86_64-linux-gnu.so(_ZN11OpticalFlow12OptimizePathERKSt6vectorI6CameraSaIS1_EEiiRKSt8functionIFdRK3RayEEdNS_18OptimizationMethodE+0x22) [0x7fa5d153bcb2]
/home/name/Programs/blender-2.83.0-linux64/2.83/python/lib/python3.7/optFlowCam.cpython-37m-x86_64-linux-gnu.so(+0x3d910) [0x7fa5d1533910]
/home/name/Programs/blender-2.83.0-linux64/2.83/python/lib/python3.7/optFlowCam.cpython-37m-x86_64-linux-gnu.so(+0x317ed) [0x7fa5d15277ed]
./blender(_PyMethodDef_RawFastCallKeywords+0x2f3) [0x570f373]
./blender(_PyCFunction_FastCallKeywords+0x25) [0x570f3f5]
./blender(_PyEval_EvalFrameDefault+0x7468) [0xc0fb48]
./blender(_PyEval_EvalCodeWithName+0xadc) [0x57c0d8c]
./blender(PyEval_EvalCodeEx+0x3e) [0x57c0ebe]
./blender(PyEval_EvalCode+0x1b) [0x57c0eeb]
./blender() [0x11f35ac]
./blender() [0x1600cde]
./blender() [0xec6a93]
./blender() [0xec6d07]
./blender(WM_operator_name_call_ptr+0x1a) [0xec720a]
./blender() [0x14f2082]
./blender() [0x15020d5]
./blender() [0xeca877]
./blender() [0xecaecc]
./blender(wm_event_do_handlers+0x310) [0xecb5e0]
./blender(WM_main+0x20) [0xec2230]
./blender(main+0x321) [0xb4bfd1]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf3) [0x7fa5facb50b3]
./blender() [0xc11c0c]

Я использую Eigen для линейного вычисления алгебры и pybind11 для компиляции в модуль python. Все типы Eigen имеют фиксированный размер, поскольку мне не нужно, чтобы они были динамическими c (возможная причина проблемы) . Я компилирую с gcc (Ubuntu 9.3.0-10ubuntu2) 9.3.0 на Ubuntu 20.04. В настоящее время я использую стандарт С ++ 11, но это не является обязательным требованием.

Текущие результаты

С faulthandler.enabled () он дает мне

Fatal Python error: Segmentation fault

Current thread 0x00007fa5fab18040 (most recent call first):
  File "/Text", line 16 in <module>

Я уже обнаружил, что it вылетает в той же строке программы, когда предполагается, что результат умножения матрицы на вектор должен быть возвращен и вставлен в std :: vector. Я распечатал вектор и матрицу заранее, чтобы убедиться, что они не содержат мусора и все работало нормально.

Я также пытался сохранить их в промежуточной переменной и распечатать, а затем он вылетает при печати. Само умножение , похоже, не вызывает segfault .

Я подумал, я пытаюсь вызвать функцию, где она происходит, непосредственно из Blender, но затем она работает и возвращает результат без segfault .

Я подозреваю, что это какая-то проблема с выравниванием памяти и пробовал все, что предлагалось здесь и в документальном фильме Eigen. А именно, я использую Eigen::aligned_allocator в каждом std :: vector, передаю только объекты Eigen как const & и имею EIGEN_MAKE_ALIGNED_OPERATOR_NEW в классах камеры и лучей, которые имеют члены типа Eigen.

Использование #define EIGEN_DONT_VECTORIZE и #define EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT дало мне лишь частичный успех. Он больше не обнаруживает sh в той же строке, что и раньше . Как ни странно, если я также добавлю cout перед возвратом, функция завершится и вернется.

Части, в которых происходят сбои :

Проект не публикуется c, а код C ++ довольно длинный, поэтому я включаю только его части. Дайте мне знать, если вам понадобится больше. Все остальное очень похоже, поэтому, если что-то концептуально не так, вероятно, и здесь тоже. Это не минимальный пример (и он содержит несколько отладочных отпечатков), так как я не знаю, почему это происходит, и ошибка не всегда связана с одной и той же частью.

// in header

// this helped somehow
#define EIGEN_DONT_VECTORIZE
#define EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT
// ***********************************

#include <iostream>
#include <numeric>
#include <array>
#include <vector>
#include <Eigen/Dense>
#include <Eigen/StdVector>
#include "matrix_types.h"
#include "camera.h"

// *******************************************************************************
// Vector9d is a typedef

// in cpp
Vector9d _z(const Camera& cam, const Vector9d& derivX, int x_dir, int y_dir, const std::function<double(const Ray&)>& depthTest){

    Eigen::IOFormat HeavyFmt(Eigen::FullPrecision, 0, ", ", ",\n", "[", "]", "[", "]");

    Matrix9d M0 = OpticalFlow::M(cam, x_dir, y_dir, depthTest);
    std::cout << "M_\n" << M0.format(HeavyFmt) << "\n" <<std::endl;

    Vector9d z = M0 * derivX;

    return z;
}

std::vector<Vector9d, Eigen::aligned_allocator<Vector9d>> OpticalFlow::GradPathError(const std::vector<Camera>& pathPositions, int x_dir, int y_dir, const std::function<double(const Ray&)>& depthTest, double h){

    int n = pathPositions.size()-1;
    Eigen::IOFormat HeavyFmt(Eigen::FullPrecision);
    Eigen::IOFormat HeavyMtxFmt(Eigen::FullPrecision, 0, ", ", ",\n", "[", "]", "[", "]");

    std::vector<Vector9d, Eigen::aligned_allocator<Vector9d>> gradPE;
    gradPE.reserve(n+1);

    // save values that will be used more often in calculations
    std::vector<Vector9d, Eigen::aligned_allocator<Vector9d>> derivXs;
    std::vector<Vector9d, Eigen::aligned_allocator<Vector9d>> zs;
    std::vector<std::array<Matrix9d, 9>> gradMs;
    derivXs.reserve(n+1);
    zs.reserve(n+1);
    gradMs.reserve(n+1);

    for(int i = 0; i<n+1; ++i){

        derivXs.push_back(_derivCamPath(pathPositions, i));

        Camera cam = pathPositions[i];
        Vector9d derivX = _derivCamPath(pathPositions, i);

        zs.push_back(_z(cam, derivX, x_dir, y_dir, depthTest)); // <--- crashed here, if vectorization not turned off
        gradMs.push_back(GradM(cam, x_dir, y_dir, depthTest, h));
    }

    for(int i = 0; i<n+1; ++i){
        Vector9d derivZ = _derivZ(zs, i);
        std::cout << "Zt_" << i << "\n" << derivZ.format(HeavyFmt) << "\n" << std::endl;
        gradPE.push_back(1.0/(n+1) * _w(derivZ, derivXs[i], gradMs[i]));
    }

    // if this is included and vectorization turned off, it doesn't crash
    // std::cout << "end" << std::endl;

    return gradPE; // <-- crash here if vectorization is off
}

Надеюсь, кто-то может мне помочь найти причину или что еще я могу попытаться отследить дальше. Я не очень разбираюсь в C ++, поэтому в коде могут быть очевидные проблемы.

1 Ответ

1 голос
/ 20 июня 2020

Думаю, я нашел причину.

Эта строка ./blender(_ZN5Eigen8IOFormatD1Ev+0xd3) [0x2041673] на самом деле назвала виновника в не очень удобочитаемом формате. Я использовал gdb для отладки вызова python из Blender и в обратной трассировке та же строка #0 0x0000000002041673 in Eigen::IOFormat::~IOFormat() ()

Проблема заключалась в том, что я использовал Eigen::IOFormat в своей программе для отладки печати матриц и векторов для упрощения копирование в другую программу, где я просто хотел проверить правильность значений. Вы можете увидеть это в коде отрывка, который я разместил в вопросе. Я использовал его только в этих двух функциях, а ошибка сегментации возникла только в этих двух функциях. Возможно, что-то еще не так, но пока, похоже, это работает.

...