#c #pybind11
#c #pybind11
Вопрос:
Я пытаюсь написать расширение C с помощью pybind11. Функция в конечном итоге примет несколько numpy-массивов в качестве входных данных и вернет несколько numpy-массивов в качестве выходных данных. Я пытался напрямую передать целевые numpy-массивы и изменить значения на месте в функции C .
Я тестирую со следующим кодом:
C
#include "pybind11/pybind11.h"
#include "pybind11/numpy.h"
namespace py = pybind11;
int nparraytest(py::array_t<float> A, py::array_t<float> B, py::array_t<float> C, py::array_t<float> D) {
py::buffer_info Abuf = A.request();
py::buffer_info Bbuf = B.request();
py::buffer_info Cbuf = C.request();
py::buffer_info Dbuf = D.request();
int lxA = Abuf.shape[0];
double* Aptr = (double*)Abuf.ptr;
double* Bptr = (double*)Bbuf.ptr;
double* Cptr = (double*)Cbuf.ptr;
double* Dptr = (double*)Dbuf.ptr;
for (int i = 0; i < lxA; i ) {
int i30 = 3 * i;
int i31 = i30 1;
int i32 = i30 2;
//optionA
//Cptr[i30] = Aptr[i30];
//Cptr[i31] = Aptr[i31];
//Cptr[i32] = Aptr[i32];
//Option B
Cptr[i30] = Aptr[i30];
Cptr[i31] = Aptr[i31];
Cptr[i32] = Bptr[2];
Dptr[i30] = Aptr[i30];
Dptr[i31] = Aptr[i31];
Dptr[i32] = Aptr[i32];
}
return lxA;
}
PYBIND11_MODULE(SeqRT, m) {
m.def("nparraytest", amp;nparraytest, "Test");
}
python
import numpy as np
import SeqRT
if __name__ == '__main__':
#initialize arrays
A = np.arange(15, dtype = np.float32).reshape((5,3))
B = np.arange(15, dtype = np.float32).reshape((5,3))
C = np.zeros((5,3), dtype = np.float32)
D = np.zeros((5,3), dtype = np.float32)
lxA = SeqRT.nparraytest(A, B, C, D)
print(lxA)
print(A)
print(B)
print(C)
print(D)
Теперь, независимо от того, использую ли я код в опции A или опции B, массивы A, B и D всегда заканчиваются так, как ожидалось, а также массив C, т.е.
[[ 0. 1. 2.]
[ 3. 4. 5.]
[ 6. 7. 8.]
[ 9. 10. 11.]
[12. 13. 14.]]
Однако с опцией B я получаю этот результат для массива C
[[ 0. 1. 2.]
[ 3. 4. 5.]
[ 6. 7. 8.]
[ 9. 4. 5.]
[12. 13. 14.]]
Как вы можете видеть, значения 10. и 11. отличаются. Фактически, при другом вводе в виде массива B также значения 4. и 5. могут оказаться довольно случайными.
Вместо этого я ожидал бы этого:
[[ 0. 1. 2.]
[ 3. 4. 2.]
[ 6. 7. 2.]
[ 9. 10. 2.]
[12. 13. 2.]]
Я не знаю, в чем моя ошибка:
- Это связано с неправильным использованием массивов pybind / numpy?
- Это общая ошибка индексации C ?
- Кроме того, хорош ли этот метод на месте или я должен создать два буферных массива и упаковать их в виде кортежа для возврата?
Комментарии:
1. После исправления
double* Aptr = (double*)Abuf.ptr;
(должно быть 32-разряднымfloat
) я не могу воспроизвести это. Вывод для C такой, как вы указали выше.2. Спасибо! Я тоже исправил это сейчас. В другом тестовом коде, который я использовал сейчас, я дополнительно должен был убедиться, что numpy-массивы, переданные в качестве входных данных, были непрерывными в памяти.