मैं अभी भी एक पूरी तरह से संतोषजनक समाधान नहीं मिला है, लेकिन फिर भी वहाँ कुछ है कोई सीपीथॉन में बहुत कम ओवरहेड के साथ पॉइंटर प्राप्त करने के लिए कर सकता है। सबसे पहले, कारण बताए गए दोनों तरीकों इतनी धीमी हैं कि .ctypes
और .__array_interface__
ऑन-डिमांड विशेषताओं हैं, जो array_ctypes_get()
और array_interface_get()
numpy/numpy/core/src/multiarray/getset.c
में सेट हैं। पहला आयात ctypes और numpy.core._internal._ctypes
उदाहरण बनाता है, जबकि दूसरा एक नया शब्दकोश बनाता है और डेटा पॉइंटर के अलावा बहुत सारी अनावश्यक सामग्री के साथ इसे पॉप्युलेट करता है।
कुछ भी नहीं इस भूमि के ऊपर के बारे में अजगर स्तर पर कर सकते हैं नहीं है, लेकिन एक सी-स्तर पर एक माइक्रो मॉड्यूल है कि भूमि के ऊपर से ज्यादातर को नजरअंदाज लिख सकते हैं: हमेशा की तरह
#include <Python.h>
#include <numpy/arrayobject.h>
PyObject *_get_ptr(PyObject *self, PyObject *obj) {
return PyLong_FromVoidPtr(PyArray_DATA(obj));
}
static PyMethodDef methods[] = {
{"_get_ptr", _get_ptr, METH_O, "Wrapper to PyArray_DATA()"},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC initaccel(void) {
Py_InitModule("accel", methods);
}
संकलित एक के रूप में setup.py
में एक्सटेंशन, और आयात
try:
from accel import _get_ptr
def get_ptr(x):
return C.cast(_get_ptr(x), p_t)
except ImportError:
get_ptr = get_ptr_array
PyPy पर, के रूप में from accel import _get_ptr
असफल हो जायेगी और get_ptr
वापस get_ptr_array
तक कम हो जाएगा, जो Numpypy साथ काम करता है।
जहां तक प्रदर्शन चलता है, हल्के वजन सी फ़ंक्शन कॉल के लिए, ctypes + accel._get_ptr()
देशी सीपीथन एक्सटेंशन की तुलना में काफी धीमी है, जो अनिवार्य रूप से कोई ओवरहेड नहीं है। यह get_ptr_ctypes()
और get_ptr_array()
से अधिक तेज़ है, ताकि ओवरहेड मध्यम-वजन सी फ़ंक्शन कॉल के लिए महत्वहीन हो सके।
किसी ने पीपीपी के साथ संगतता प्राप्त की है, हालांकि मुझे यह कहना है कि मेरे वैज्ञानिक गणना अनुप्रयोगों के लिए पीईपीई का मूल्यांकन करने की कोशिश करने में काफी समय व्यतीत करने के बाद, मुझे इसके लिए भविष्य नहीं दिखता है जब तक कि वे (काफी हद तक जिद्दी) पूर्ण सीपीथन एपीआई का समर्थन करने से इंकार कर दिया।
अद्यतन
मैंने पाया कि ctypes.cast()
अब accel._get_ptr()
पेश करने के बाद टोंटी होता जा रहा था। इंटरफ़ेस में सभी पॉइंटर्स को ctypes.c_void_p
के रूप में घोषित करके जानवरों से छुटकारा पा सकता है।
def get_ptr_ctypes2(x):
return x.ctypes._data
def get_ptr_array(x):
return x.__array_interface__['data'][0]
try:
from accel import _get_ptr as get_ptr
except ImportError:
get_ptr = get_ptr_array
यहाँ, get_ptr_ctypes2()
छिपा ndarray.ctypes._data
विशेषता सीधे पहुंच कर डाली से बचा जाता है: यह है कि मैं क्या साथ समाप्त हो गया है। यहाँ अजगर से भारी वजन और हल्के वजन सी कार्यों फोन करने के लिए कुछ समय परिणाम हैं:
heavy C (few calls) light C (many calls)
ctypes + get_ptr_ctypes(): 0.71 s 15.40 s
ctypes + get_ptr_ctypes2(): 0.68 s 13.30 s
ctypes + get_ptr_array(): 0.65 s 11.50 s
ctypes + accel._get_ptr(): 0.63 s 9.47 s
native CPython: 0.62 s 8.54 s
Cython (no decorators): 0.64 s 9.96 s
तो, accel._get_ptr()
साथ और कोई ctypes.cast()
रों, ctypes 'गति वास्तव में एक देशी CPython विस्तार के साथ प्रतिस्पर्धी है। तो मैं बस जब तक किसी को h5py
, matplotlib
और scipy
पुनर्लेखन ctypes के साथ कुछ भी गंभीर के लिए PyPy कोशिश करने के लिए सक्षम होने के लिए इंतजार करना पड़ता है ...
दुर्भाग्य से, 'scipy.weave' सी कोड CPython एपीआई का उपयोग कर के उत्पादन की तुलना और कुछ नहीं (करता है '# शामिल करें'), जो 'पीपीपी' के साथ काम नहीं करेगा। सीपीथॉन एपीआई के भीतर, 'PyArray_DATA() 'numpy arrays के डेटा सेक्शन में पॉइंटर प्राप्त करने का सबसे प्रभावी तरीका है, लेकिन यह PyPy के लिए पोर्टेबल नहीं है। –
Stefan