gpt4 book ai didi

python - numpy 通过 ctypes 调用 sse2

转载 作者:太空狗 更新时间:2023-10-29 19:28:45 27 4
gpt4 key购买 nike

简而言之,我正在尝试从 python 调用共享库,更具体地说,是从 numpy。共享库是使用 sse2 指令在 C 中实现的。启用优化,即使用 -O2 或 –O1 构建库,我在通过 ctypes 调用共享库时遇到奇怪的段错误。禁用优化 (-O0),一切都按预期进行,就像将库直接链接到 c 程序(优化或未优化)时的情况一样。您会在附件中找到一个片段,其中展示了我系统上描述的行为。启用优化后,gdb 在 __builtin_ia32_loadupd (__P) at emmintrin.h:113 报告段错误。 __P 的值被报告为优化掉。

测试.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

测试.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)

从 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
导出 LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:.
./testc
... 有效。

我的系统:

  • Ubuntu Linux i686 2.6.31-22-generic
  • 编译器:gcc (Ubuntu 4.4.1-4ubuntu9)
  • Python:Python 2.6.4(r264:75706,2009 年 12 月 7 日,18:45:15)[GCC 4.4.1]
  • NumPy :1.4.0

我已经规定(参见 python 代码)y 对齐并且 x 的对齐无关紧要(我认为;显式对齐 x 并不能解决问题)。

另请注意,我在加载 b 和 f 时使用 _mm_loadu_pd 而不是 _mm_load_pd。对于 C-only 版本,_mm_load_pd 有效(如预期)。但是,当使用 ctypes 调用函数时_mm_load_pd 总是段错误(独立于优化)。

我已经尝试了好几天来解决这个问题,但没有成功……我差点把我的显示器打死。欢迎任何输入。丹尼尔

最佳答案

我只是被这个试图从 python 调用一些 SSE 代码所困扰,问题似乎是 GCC 想要假设堆栈在 16 字节边界上对齐(架构上最大的 native 类型,即SSE 类型),并使用该假设计算所有偏移量。当该假设为假时,SSE 指令将陷入困境。

答案好像是编译用

gcc -mstackrealign
这将函数序言更改为始终将堆栈对齐到 16 个字节。

关于python - numpy 通过 ctypes 调用 sse2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3045158/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com