Странный результат при настройке элементов массива (C / pybind11)

#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-массивы, переданные в качестве входных данных, были непрерывными в памяти.