pybind11 从 C++ 修改 numpy 数组
pybind11 modify numpy array from C++
编辑:现在可以用了,我不知道为什么。不要以为我改变了什么
我想用 pybind11 传入并修改一个大的 numpy 数组。因为它很大,所以我想避免复制它并返回一个新的。
代码如下:
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/numpy.h>
#include <vector>
// C++ code
void calc_sum_cost(float* ptr, int N, int M, float* ptr_cost) {
for(int32_t i = 1; i < N; i++) {
for(int32_t j = 1; j < M; j++) {
float upc = ptr[(i-1) * M + j];
float leftc = ptr[i * M + j - 1];
float diagc = ptr[(i-1) * M + j - 1];
float transition_cost = std::min(upc, std::min(leftc, diagc));
if (transition_cost == diagc) {
transition_cost += 2 * ptr_cost[i*M + j];
} else {
transition_cost += ptr_cost[i*M + j];
}
std::cout << transition_cost << std::endl;
ptr[i * M + j] = transition_cost;
}
}
}
// Interface
namespace py = pybind11;
// wrap C++ function with NumPy array IO
py::object wrapper(py::array_t<float> array,
py::array_t<float> arrayb) {
// check input dimensions
if ( array.ndim() != 2 )
throw std::runtime_error("Input should be 2-D NumPy array");
auto buf = array.request();
auto buf2 = arrayb.request();
if (buf.size != buf2.size) throw std::runtime_error("sizes do not match!");
int N = array.shape()[0], M = array.shape()[1];
float* ptr = (float*) buf.ptr;
float* ptr_cost = (float*) buf2.ptr;
// call pure C++ function
calc_sum_cost(ptr, N, M, ptr_cost);
return py::cast<py::none>(Py_None);
}
PYBIND11_MODULE(fast,m) {
m.doc() = "pybind11 plugin";
m.def("calc_sum_cost", &wrapper, "Calculate the length of an array of vectors");
}
我认为 py::array::forcecast
导致转换,因此保持输入矩阵不变(在 python 中)。当我删除它时,尽管出现运行时错误,当我删除 ::c_style
时它会运行,但在 python 中再次运行时,numpy 数组是相同的。
基本上我的问题是如何使用 pybind11 传递和修改 numpy 数组?
我刚刚遇到了同样的问题。如果从 Python 开始,您传递了一个与 C++ 参数匹配的类型的 numpy 数组,则不会发生任何转换,您可以就地修改数据,即对于 py::array_t<float>
参数,传递一个 numpy np.float32
数组。如果你碰巧传入一个 np.float64
数组(默认类型),那么 pybind11 会根据 py::array::forcecast
模板参数(默认为 py::array_t<T>
)进行转换,所以你的 C++ 函数只会得到一个numpy 数组的转换副本,返回后所有更改都将丢失。
编辑:现在可以用了,我不知道为什么。不要以为我改变了什么
我想用 pybind11 传入并修改一个大的 numpy 数组。因为它很大,所以我想避免复制它并返回一个新的。
代码如下:
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/numpy.h>
#include <vector>
// C++ code
void calc_sum_cost(float* ptr, int N, int M, float* ptr_cost) {
for(int32_t i = 1; i < N; i++) {
for(int32_t j = 1; j < M; j++) {
float upc = ptr[(i-1) * M + j];
float leftc = ptr[i * M + j - 1];
float diagc = ptr[(i-1) * M + j - 1];
float transition_cost = std::min(upc, std::min(leftc, diagc));
if (transition_cost == diagc) {
transition_cost += 2 * ptr_cost[i*M + j];
} else {
transition_cost += ptr_cost[i*M + j];
}
std::cout << transition_cost << std::endl;
ptr[i * M + j] = transition_cost;
}
}
}
// Interface
namespace py = pybind11;
// wrap C++ function with NumPy array IO
py::object wrapper(py::array_t<float> array,
py::array_t<float> arrayb) {
// check input dimensions
if ( array.ndim() != 2 )
throw std::runtime_error("Input should be 2-D NumPy array");
auto buf = array.request();
auto buf2 = arrayb.request();
if (buf.size != buf2.size) throw std::runtime_error("sizes do not match!");
int N = array.shape()[0], M = array.shape()[1];
float* ptr = (float*) buf.ptr;
float* ptr_cost = (float*) buf2.ptr;
// call pure C++ function
calc_sum_cost(ptr, N, M, ptr_cost);
return py::cast<py::none>(Py_None);
}
PYBIND11_MODULE(fast,m) {
m.doc() = "pybind11 plugin";
m.def("calc_sum_cost", &wrapper, "Calculate the length of an array of vectors");
}
我认为 py::array::forcecast
导致转换,因此保持输入矩阵不变(在 python 中)。当我删除它时,尽管出现运行时错误,当我删除 ::c_style
时它会运行,但在 python 中再次运行时,numpy 数组是相同的。
基本上我的问题是如何使用 pybind11 传递和修改 numpy 数组?
我刚刚遇到了同样的问题。如果从 Python 开始,您传递了一个与 C++ 参数匹配的类型的 numpy 数组,则不会发生任何转换,您可以就地修改数据,即对于 py::array_t<float>
参数,传递一个 numpy np.float32
数组。如果你碰巧传入一个 np.float64
数组(默认类型),那么 pybind11 会根据 py::array::forcecast
模板参数(默认为 py::array_t<T>
)进行转换,所以你的 C++ 函数只会得到一个numpy 数组的转换副本,返回后所有更改都将丢失。