首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从c++原始指针获得pybind11中的零拷贝视图?

如何从c++原始指针获得pybind11中的零拷贝视图?
EN

Stack Overflow用户
提问于 2022-09-09 14:31:14
回答 1查看 64关注 0票数 1

请考虑一下这个小例子。

mcve.cpp

代码语言:javascript
复制
#include <pybind11/pybind11.h>
#include <pybind11/operators.h>
#include <pybind11/numpy.h>

namespace py = pybind11;

class mat4 {
  public:
    mat4(float v = 1.0f) {
        data[0] = v; data[4] = 0; data[8] = 0; data[12] = 0;
        data[1] = 0; data[5] = v; data[9] = 0; data[13] = 0;
        data[2] = 0; data[6] = 0; data[10] = v; data[14] = 0;
        data[3] = 0; data[7] = 0; data[11] = 0; data[15] = v;
    }

    mat4(
        float m00, float m01, float m02, float m03,
        float m10, float m11, float m12, float m13,
        float m20, float m21, float m22, float m23,
        float m30, float m31, float m32, float m33
    ) {
        data[0] = m00; data[4] = m01; data[8] = m02; data[12] = m03;
        data[1] = m10; data[5] = m11; data[9] = m12; data[13] = m13;
        data[2] = m20; data[6] = m21; data[10] = m22; data[14] = m23;
        data[3] = m30; data[7] = m31; data[11] = m32; data[15] = m33;
    }

    float data[16];
};

PYBIND11_MODULE(bindings, m) {
    py::class_<::mat4>(m, "mat4")
        .def(py::init<float>(), py::arg("v") = 1.0f)
        .def("__getitem__", [](mat4& m, py::ssize_t i) {
            return m.data[i];
        })
        .def("__setitem__", [](mat4& m, py::ssize_t i, float v) {
            m.data[i] = v;
        })
        .def("__str__", [](mat4& m) {
            #define str_row(a,b,c,d) std::to_string(a) + "," + std::to_string(b) + "," + std::to_string(c) + "," + std::to_string(d) + ","
            return "mat4(\n"
                   "    "+str_row(m.data[0], m.data[4], m.data[8], m.data[12])+"\n"+
                   "    "+str_row(m.data[1], m.data[5], m.data[9], m.data[13])+"\n"+
                   "    "+str_row(m.data[2], m.data[6], m.data[10], m.data[14])+"\n"+
                   "    "+str_row(m.data[3], m.data[7], m.data[11], m.data[15])+"\n"+
                   ")";
        })
        .def("value_ptr", [](mat4& m) {
            return py::array_t<float>({16}, m.data);
        })
    ;
};

CMakelists.txt

代码语言:javascript
复制
cmake_minimum_required(VERSION 3.4)

project(mcve)
add_subdirectory(pybind11)


pybind11_add_module(bindings "mcve.cpp")

test.py

代码语言:javascript
复制
from build.bindings import mat4

if __name__ == "__main__":
    m = mat4(1)
    ptr = m.value_ptr()

    print("----case1----")
    print(m)
    print(ptr)

    print("----case2----")
    m[5] = 2
    m[10] = 3
    m[15] = 4
    print(m)
    print("wrong content!!! ", ptr)
    print("valid content!!! ", m.value_ptr())

如果您试图通过执行类似的操作来编译和运行上述内容:

代码语言:javascript
复制
mkdir build && cd build && cmake .. -G Ninja && cmake --build . && cd ..
python test.py

一切顺利..。您的输出应该低于:

代码语言:javascript
复制
----case1----
mat4(
    1.000000,0.000000,0.000000,0.000000,
    0.000000,1.000000,0.000000,0.000000,
    0.000000,0.000000,1.000000,0.000000,
    0.000000,0.000000,0.000000,1.000000,
)
[1. 0. 0. 0. 0. 1. 0. 0. 0. 0. 1. 0. 0. 0. 0. 1.]
----case2----
mat4(
    1.000000,0.000000,0.000000,0.000000,
    0.000000,2.000000,0.000000,0.000000,
    0.000000,0.000000,3.000000,0.000000,
    0.000000,0.000000,0.000000,4.000000,
)
wrong content!!!  [1. 0. 0. 0. 0. 1. 0. 0. 0. 0. 1. 0. 0. 0. 0. 1.]
valid content!!!  [1. 0. 0. 0. 0. 2. 0. 0. 0. 0. 3. 0. 0. 0. 0. 4.]

如您所见,在case2中原始矩阵内容已被修改,您可以看到ptr仍然显示原始内容.因此,我需要再次运行m.value_ptr(),以获得更新的数据。

因此,我的问题是,如何使用c++原始指针使用pybind11有效地创建零拷贝视图?

我已经研究了几个小时,尝试了不同的方法,但我被困住了。首先,我想了解一下上面的代码有什么问题.感觉py::array在复制数组中的内容,而不是从数组中创建视图,所以.是否有任何方法可以通过使用py::array来避免这种复制,而只需要从指针中获得一个“视图”?实现这一目标的正确方法是什么?在实际情况下,我将处理大量内存,因此复制不必要的数据根本不是一种选择。

参考文献:

EN

回答 1

Stack Overflow用户

发布于 2022-09-09 17:44:48

可能的解决办法:

代码语言:javascript
复制
    .def("value_ptr", [](mat4& m) {
        return py::array_t<float>{16, m.data, py::cast(m)};
    })

取自https://github.com/pybind/pybind11/issues/2271#issuecomment-650569067的原始参考资料

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73663733

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档