簡而言之,我試圖從Python,更具體地說,從numpy調用共享庫。共享庫使用sse2指令在C中實現。啓用優化,即使用-O2或-O1構建庫,當通過ctypes調用共享庫時,我正面臨奇怪的段錯誤。禁用優化(-O0),一切都按預期運行,就像將庫直接鏈接到c程序時一樣(優化與否)。附上你發現一個剪輯,展現了我的系統上劃定的行爲。啓用優化後,gdb會在emmintrin.h:113的__builtin_ia32_loadupd(__P)中報告段錯誤。 __P的值被報告爲已優化。numpy通過ctypes調用sse2
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;
}
編譯國旗: GCC -o libtest.so -shared -std = C99 -msse2 -fPIC -O2 -g -lm test.c的
測試。潘岳:
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)
從C調用測試按預期工作:
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;
}
編譯並撥打:
GCC -std = C99 -otestc -msse2 -L。 -ltest call_from_c.c
export LD_LIBRARY_PATH = $ {LD_LIBRARY_PATH} :.
./testc
...作品。
我的系統:
- Ubuntu Linux操作系統的i686 2.6.31-22-通用
- 編譯器:GCC(Ubuntu的4.4.1-4ubuntu9)
- 的Python:Python的2.6.4(r264:75706 ,2009年12月7日,十八點45分15秒)[GCC 4.4.1]
- numpy的:1.4.0
我已採取規定(參見Python代碼)使y對準和x的對準不應該磨砂r(我認爲;明確地對齊x並不能解決問題)。
請注意,在加載b和f時,我使用_mm_loadu_pd而不是_mm_load_pd。對於僅限C的版本,_mm_load_pd可以正常工作(如預期的那樣)。但是,當通過ctypes使用 _mm_load_pd調用函數時總是出現segfaults(與優化無關)。
我已經嘗試了幾天來解決這個問題沒有成功......而我正在瀕死我的顯示器死亡。任何輸入歡迎。 丹尼爾
如果您從C調用「測試」函數,是否會得到相同的錯誤? – Tarantula 2010-06-15 23:01:09
編號從C調用測試運行平穩...我已經更新了原來的職位,並從C的示例調用。 – Daniel 2010-06-16 11:03:40
如何從等式中刪除numpy並直接使用ctypes? – tonfa 2010-08-22 14:45:41