Tôi đang viết một phần mở rộng C cho chương trình Python của mình cho mục đích tốc độ và chạy vào một số hành vi rất lạ khi cố gắng chuyển vào mảng 3 chiều. Nó hoạt động với một mảng 2 chiều, nhưng tôi chắc chắn rằng tôi đang vặn vẹo thứ gì đó với các con trỏ cố gắng làm cho nó hoạt động với chiều thứ 3. Nhưng đây là một phần kỳ lạ. Nếu tôi chỉ chuyển vào mảng 3-D, lỗi đó sẽ bị lỗi với Lỗi Bus. Nếu (bằng Python) tôi tạo biến của tôi dưới dạng mảng 2D trước, sau đó ghi đè lên nó bằng một mảng 3D, nó hoạt động hoàn hảo. Nếu biến này là mảng trống trước tiên và sau đó là mảng 3D, biến đó sẽ gặp sự cố Seg Fault. Làm thế nào điều đó có thể xảy ra?Vượt qua mảng numpy 3 chiều đến C
Ngoài ra, bất kỳ ai cũng có thể giúp tôi có được mảng 3D hoạt động không? Hoặc tôi có nên bỏ cuộc và vượt qua một mảng 2D và tự định hình lại nó không?
Đây là mã C của tôi:
static PyObject* func(PyObject* self, PyObject* args) {
PyObject *list2_obj;
PyObject *list3_obj;
if (!PyArg_ParseTuple(args, "OO", &list2_obj, &list3_obj))
return NULL;
double **list2;
double ***list3;
//Create C arrays from numpy objects:
int typenum = NPY_DOUBLE;
PyArray_Descr *descr;
descr = PyArray_DescrFromType(typenum);
npy_intp dims[3];
if (PyArray_AsCArray(&list2_obj, (void **)&list2, dims, 2, descr) < 0 || PyArray_AsCArray(&list3_obj, (void ***)&list3, dims, 3, descr) < 0) {
PyErr_SetString(PyExc_TypeError, "error converting to c array");
return NULL;
}
printf("2D: %f, 3D: %f.\n", list2[3][1], list3[1][0][2]);
}
Và đây là mã Python của tôi mà gọi hàm trên:
import cmod, numpy
l2 = numpy.array([[1.0,2.0,3.0], [4.0,5.0,6.0], [7.0,8.0,9.0], [3.0, 5.0, 0.0]])
l3 = numpy.array([[2,7, 1], [6, 3, 9], [1, 10, 13], [4, 2, 6]]) # Line A
l3 = numpy.array([]) # Line B
l3 = numpy.array([[[2,7, 1, 11], [6, 3, 9, 12]],
[[1, 10, 13, 15], [4, 2, 6, 2]]])
cmod.func(l2, l3)
Vì vậy, nếu tôi nhận xét ra cả dòng A và B, nó bị treo với một Lỗi bus. Nếu Dòng A ở đó, nhưng Dòng B được nhận xét, nó chạy đúng cách mà không có lỗi. Nếu Dòng B ở đó nhưng Dòng A được nhận xét, nó sẽ in số chính xác nhưng sau đó là lỗi Seg. Cuối cùng, nếu cả hai dòng có mặt, nó cũng in các số chính xác và sau đó là lỗi Seg. Cái quái gì đang diễn ra ở đây vậy?
EDIT: Ok. Wow. Vì vậy, tôi đã sử dụng int
bằng Python nhưng gọi chúng là double
trong C. Và điều đó hoạt động tốt với mảng 1D và 2D. Nhưng không phải 3D. Vì vậy, tôi đã thay đổi định nghĩa Python của l3 để nổi, và bây giờ tất cả hoạt động tuyệt vời (Cảm ơn bạn rất nhiều Bi Rico).
Nhưng hiện tại, hành vi lạ hơn với Đường A & B! Bây giờ nếu cả hai dòng được nhận xét, chương trình hoạt động. Nếu dòng B là hiện tại nhưng A được nhận xét, nó hoạt động và ditto nếu cả hai đều không được chú ý. Nhưng nếu Line A có mặt và B được nhận xét, tôi sẽ gặp lại lỗi Bus tuyệt vời đó. Tôi thực sự muốn tránh những điều này trong tương lai, do đó, có ai có bất kỳ đầu mối tại sao việc khai báo một biến Python có thể có loại tác động?
CHỈNH SỬA 2: Vâng, tất cả chúng đều là do mảng numpy 3 chiều mà tôi truyền vào. Nếu tôi chỉ truyền trong mảng 1 hoặc 2-D, nó hoạt động như dự kiến và thao tác của các biến Python khác không làm gì cả. Điều này khiến tôi tin rằng vấn đề nằm ở đâu đó trong tính toán tham chiếu của Python. Trong mã C, số tham chiếu được giảm nhiều hơn mức cần thiết cho các mảng 3-D, và khi hàm đó trả về Python cố gắng dọn sạch các đối tượng và cố gắng xóa một con trỏ NULL. Đây chỉ là phỏng đoán của tôi, và tôi đã cố gắng để Py_INCREF();
tất cả mọi thứ tôi có thể nghĩ đến không có kết quả. Tôi đoán tôi sẽ chỉ được sử dụng một mảng 2D và định hình lại nó trong C.
Bạn có chắc chắn rằng '(void **)' là đúng, nên bạn không chỉ cần vượt qua trong một '(void *)'? – seberg
C của tôi hút nhưng ... Không phải là biểu hiện của bạn trong 'if' ngắn mạch nếu cuộc gọi đầu tiên để' PyArray_AsCArray' suceeds? Rất có thể là cuộc gọi thứ hai, tức là cuộc gọi thứ hai cho 'list3', không bao giờ được thực hiện. – Jaime
@seberg Tôi không khẳng định rằng '(void **)' là đúng, nhưng '(void *)' gây ra lỗi Bus. @Jaime Không, hàm đó trả về giá trị âm chỉ khi nó không thành công, rất có thể nếu malloc nó gọi không thành công. – DaveTheScientist