के माध्यम से numpy कॉलिंग sse2 संक्षेप में, मैं अजगर से, विशेष रूप से, पायथन से साझा लाइब्रेरी में कॉल करने का प्रयास कर रहा हूं। एसएसई 2 निर्देशों का उपयोग कर साझा पुस्तकालय सी में लागू किया गया है। अनुकूलन को सक्षम करना, यानी पुस्तकालय का निर्माण -ओ 2 या -ओ 1 के साथ, मुझे ctypes के माध्यम से साझा लाइब्रेरी में कॉल करते समय अजीब segfaults का सामना करना पड़ रहा है। ऑप्टिमाइज़ेशन को अक्षम करना (-O0), सबकुछ अपेक्षित रूप से काम करता है, जैसा कि लाइब्रेरी को सी-प्रोग्राम से सीधे जोड़ने (अनुकूलित या नहीं) के मामले में होता है। संलग्न एक स्निप जो मुझे मेरे सिस्टम पर चित्रित व्यवहार प्रदर्शित करता है। ऑप्टिमाइज़ेशन सक्षम होने के साथ, gdb emmintrin.h: 113 पर __builtin_ia32_loadupd (__P) में एक segfault की रिपोर्ट करता है। __P का मान ऑप्टिमाइज़ आउट के रूप में रिपोर्ट किया गया है।ctypes
test.c:
#include <emmintrin.h>
#include <complex.h>
void test(const int m, const double* x, double complex* y) {
int i;
__m128d _f, _x, _b;
double complex f __attribute__((aligned(16)));
double complex b __attribute__((aligned(16)));
__m128d* _p;
b = 1;
_b = _mm_loadu_pd((double *) &b);
_p = (__m128d*) y;
for(i=0; i<m; ++i) {
f = cexp(-I*x[i]);
_f = _mm_loadu_pd((double *) &f);
_x = _mm_loadu_pd((double *) &x[i]);
_f = _mm_shuffle_pd(_f, _f, 1);
*_p = _mm_add_pd(*_p, _f);
*_p = _mm_add_pd(*_p, _x);
*_p = _mm_mul_pd(*_p,_b);
_p++;
}
return;
}
संकलक झंडे: जीसीसी -ओ libtest.so कमरा साझा -std = c99 -msse2 -fPIC -O2 जी -lm test.c
परीक्षण। py:
import numpy as np
import os
def zerovec_aligned(nr, dtype=np.float64, boundary=16):
'''Create an aligned array of zeros.
'''
size = nr * np.dtype(dtype).itemsize
tmp = np.zeros(size + boundary, dtype=np.uint8)
address = tmp.__array_interface__['data'][0]
offset = boundary - address % boundary
return tmp[offset:offset + size].view(dtype=dtype)
lib = np.ctypeslib.load_library('libtest', '.')
lib.test.restype = None
lib.test.argtypes = [np.ctypeslib.ctypes.c_int,
np.ctypeslib.ndpointer(np.float64, flags=('C', 'A')),
np.ctypeslib.ndpointer(np.complex128, flags=('C', 'A', 'W'))]
n = 13
y = zerovec_aligned(n, dtype=np.complex128)
x = np.ones(n, dtype=np.float64)
# x = zerovec_aligned(n, dtype=np.float64)
# x[:] = 1.
lib.test(n,x,y)
सी से परीक्षण कॉलिंग की उम्मीद के रूप में काम करता है:
call_from_c.c:
#include <stdio.h>
#include <complex.h>
#include <stdlib.h>
#include <emmintrin.h>
void test(const int m, const double* x, double complex* y);
int main() {
int i;
const int n = 11;
double complex *y = (double complex*) _mm_malloc(n*sizeof(double complex), 16);
double *x = (double *) malloc(n*sizeof(double));
for(i=0; i<n; ++i) {
x[i] = 1;
y[i] = 0;
}
test(n, x, y);
for(i=0; i<n; ++i)
printf("[%f %f]\n", creal(y[i]), cimag(y[i]));
return 1;
}
संकलित करें और कॉल करें:
जीसीसी -std = c99 -otestc -msse2 एल। -ltest call_from_c.c
निर्यात LD_LIBRARY_PATH = $ {LD_LIBRARY_PATH}:।
./testc
... काम करता है।
मेरे सिस्टम:
- उबंटू लिनक्स i686 2.6.31-22-सामान्य
- संकलक: जीसीसी (उबंटू 4.4.1-4ubuntu9)
- अजगर: अजगर 2.6.4 (r264: 75,706 , 7 दिसंबर 2009, 18:45:15) [जीसीसी 4.4.1]
- Numpy: 1.4.0
मैं ले लिया है प्रावधानों (सीएफ अजगर कोड) कि y गठबंधन है और एक्स के संरेखण मैट नहीं होना चाहिए आर (मुझे लगता है; एक्स को स्पष्ट रूप से संरेखित करना समस्या को हल नहीं करता है)।
ध्यान दें कि मैं b और f लोड करते समय _mm_load_pd के बजाय _mm_loadu_pd का उपयोग करता हूं। सी-केवल संस्करण _mm_load_pd कार्यों के लिए (अपेक्षित के रूप में)। हालांकि, _mm_load_pd हमेशा segfaults (अनुकूलन से स्वतंत्र) का उपयोग कर ctypes के माध्यम से फ़ंक्शन को कॉल करते समय।
मैंने सफलता के बिना इस मुद्दे को हल करने के लिए कई दिनों की कोशिश की है ... और मैं अपने मॉनीटर को मौत के लिए मारने के कगार पर हूं। कोई इनपुट स्वागत है। डैनियल
आप एक ही त्रुटि मिलती है अगर आप सी से "परीक्षण" फ़ंक्शन को कॉल किया? सी से – Tarantula
नंबर कॉलिंग परीक्षण सुचारू रूप से चलाता है ... मैं सी – Daniel
से एक उदाहरण कॉल समीकरण से numpy को दूर करने और सीधे ctypes का उपयोग कर के बारे में क्या साथ मूल पोस्ट अपडेट किया है? – tonfa