c – 多余的if-else如何帮助优化?

我正在阅读
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 in tout * 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
点赞