栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

从Cython代码生成SIMD指令

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

从Cython代码生成SIMD指令

您的代码中有两个问题(使用选项

-a
使其可见):

  1. numpy数组的索引效率不高
  2. 你忘
    int
    cdef sum=0

考虑到这一点,我们得到:

cpdef int f(np.ndarray[np.int_t] f):  ##HERE    assert f.dtype == np.int    cdef int array_length =  f.shape[0]    cdef int sum = 0       ##HERE    cdef int k    for k in range(array_length):        sum += f[k]    return sum

对于循环,以下代码:

int __pyx_t_5;int __pyx_t_6;Py_ssize_t __pyx_t_7;....__pyx_t_5 = __pyx_v_array_length;for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) {   __pyx_v_k = __pyx_t_6;   __pyx_t_7 = __pyx_v_k;   __pyx_v_sum = (__pyx_v_sum + (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_int_t *, __pyx_pybuffernd_f.rcbuffer->pybuffer.buf, __pyx_t_7, __pyx_pybuffernd_f.diminfo[0].strides)));

}

这样做还不错,但是对于优化器而言,却不如人类编写的普通代码那么容易。正如您已经指出的那样,

__pyx_pybuffernd_f.diminfo[0].strides
在编译时未知,这会阻止矢量化。

但是,使用类型化的内存视图时,您会得到更好的结果,即:

cpdef int mf(int[::1] f):    cdef int array_length =  len(f)...

这导致了不透明的C代码-至少是我的编译器可以更好地优化:

 __pyx_t_2 = __pyx_v_array_length;  for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {    __pyx_v_k = __pyx_t_3;    __pyx_t_4 = __pyx_v_k;    __pyx_v_sum = (__pyx_v_sum + (*((int *) (  ((char *) (((int *) __pyx_v_f.data) + __pyx_t_4)) ))));  }

这里最关键的是,我们要让cython清楚,内存是连续的,即

int[::1]
int[:]
numpy数组所看到的相比,
stride!=1
必须考虑可能的情况。

在这种情况下,用Cython生成的C代码导致同一汇编作为代码我会写。正如crisb指出的那样,相加

-march=native
会导致向量化,但是在这种情况下,两个函数的汇编器将再次略有不同。

但是,以我的经验,编译器通常会遇到一些问题,无法优化由cython创建的循环,并且/或者容易遗漏一个细节,从而阻止生成真正好的C代码。因此,我处理工作循环的策略是用纯C语言编写它们,并使用cython来包装/访问它们-
通常会更快一些,因为也可以使用专用的编译器标志来捕获此代码而不会影响整个Cython-模块。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/624179.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号