Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 冗余if else如何帮助优化?_C_Numpy_If Statement_Optimization_Macros - Fatal编程技术网

C 冗余if else如何帮助优化?

C 冗余if else如何帮助优化?,c,numpy,if-statement,optimization,macros,C,Numpy,If Statement,Optimization,Macros,我正在阅读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; \

我正在阅读
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)
我觉得很奇怪,尤其是
一元循环\u FAST
中的注释。
如果使用
if A then X else X
逻辑进行优化,这里会发生什么?

如果没有更多的上下文,您无法判断
numpy
代码片段可以实现什么样的优化,但它可能类似于此简化示例:

#define LOOP(op) for (int i = 0; i < n; i++) op

void f(int *a, int *b, int n, int c) {
  if (c == 1) {
    LOOP(a[i] += b[i] * c);
  }
  else {
    LOOP(a[i] += b[i] * c);
  }
}
#为(int i=0;i
现代的编译器可以。在上面的示例中,您可以简单地在第一个分支中编写
循环(a[i]+=b[i])
,但是如果
if
语句是另一个以
op
为参数的宏的一部分,这是不可能的

基本思想是强制编译器为多个路径生成代码,其中一些路径具有可用于某些优化的先决条件。

此剪辑来自

此特定片段为单个参数
ufunc
定义循环宏,类似于
np.abs

此剪辑之前的评论是

/**具有连续专门化的循环*op应该是在
tin-in
上工作的代码,并且*将结果存储在
tout*out
*与NPY\u GCC\u OPT\u 3结合以允许自动矢量化*应该仅在值得避免代码膨胀的情况下使用*/

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

同样,如果事情只需要做一次,那么为什么
do{…}while(0)?@ SAMErkn DO {…}(0)是通用的并且有目的,参见。也许它告诉编译器考虑特殊的情况,其中<代码> tout 数组与<代码> TIN /代码>相同,例如<代码> NP.Sin(A,out = A)
。我认为分支本身要比乘法运算昂贵得多。但分支只执行一次。在分支后多次乘法。后一种情况下产生的时间差是否不需要
malloc
新的b空间?
b
在这两种情况下都是预定义的。无论如何,《纽约时报》只是暗示,而不是证明。