我正在阅读
Python的numpy库的源代码,并找到以下代码段.它似乎在向量上执行元素操作(numpy.ndarray).例如,numpy.multiply([1,2,3],[4,5,6])将得到结果[4,10,18]
#define BASE_UNARY_LOOP(tin, tout, op) \
UNARY_LOOP { \
const tin in = *(tin *)ip1; \
tout * out = (tout *)op1; \
op; \
}
#define UNARY_LOOP_FAST(tin, tout, op) \
do { \
/* condition allows compiler to optimize the generic macro */ \
if (IS_UNARY_CONT(tin, tout)) { \
if (args[0] == args[1]) { \
BASE_UNARY_LOOP(tin, tout, op) \
} \
else { \
BASE_UNARY_LOOP(tin, tout, op) \
} \
} \
else { \
BASE_UNARY_LOOP(tin, tout, op) \
} \
} \
while (0)
这看起来很奇怪,尤其是UNARY_LOOP_FAST中的评论.
通过使用A然后X else X逻辑来优化,这里发生了什么?
最佳答案 这个剪辑来自
https://github.com/numpy/numpy/blob/master/numpy/core/src/umath/loops.c.src
这个特定的剪辑定义了单个参数ufunc的循环宏,类似于np.abs.
此剪辑前的评论是
/* * loop with contiguous specialization * op should be the code working on
tin in
and * storing the result intout * out
* combine with NPY_GCC_OPT_3 to allow autovectorization * should only be used where its worthwhile to avoid code bloat */
ufunc设计允许使用像np.sin(a,out = b).显然它告诉编译器考虑tout数组与tin相同的特殊情况,例如np.sin(a,out = a).
类似地,快速二进制ufunc宏允许三个数组之间的同一性,np.add(a,b,out = c),其可以将其实现为c = a b,a = b,b = a.
这些时间差异表明在args [0] == args [1]的情况下存在适度的优化
In [195]: a=np.ones((100,100))
In [197]: %%timeit b=np.ones((100,100))
...: np.sin(a, out=b)
1000 loops, best of 3: 343 µs per loop
In [198]: %%timeit b=np.ones((100,100))
...: np.sin(b, out=b)
1000 loops, best of 3: 279 µs per loop