Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.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++ 条件上的按位操作设置变量_C++_C_Performance_Optimization_Bit Manipulation - Fatal编程技术网

C++ 条件上的按位操作设置变量

C++ 条件上的按位操作设置变量,c++,c,performance,optimization,bit-manipulation,C++,C,Performance,Optimization,Bit Manipulation,在C/C++应用程序中,我有三个变量——x、y和z。当z=3时,我想设置x=y。我可以使用乘法来实现这一点: x = y * (z == 3) 但这是在一个大循环中调用的,IMUL将占用4个CPU周期。我希望能找到一个需要1个CPU周期的位操作 编辑:编译器MSVC 64位编译、平台Win 7 64、x86体系结构、Ivy Bridge或Haswell。这必须是至少两个操作(可能是3个) 评估z==3 分配给x (可能)评估y+y 我能想到的写它的最有效的方法是使用三元表达式 x = (z =

在C/C++应用程序中,我有三个变量——x、y和z。当z=3时,我想设置x=y。我可以使用乘法来实现这一点:

x = y * (z == 3)
但这是在一个大循环中调用的,IMUL将占用4个CPU周期。我希望能找到一个需要1个CPU周期的位操作


编辑:编译器MSVC 64位编译、平台Win 7 64、x86体系结构、Ivy Bridge或Haswell。

这必须是至少两个操作(可能是3个)

  • 评估
    z==3
  • 分配给
    x
  • (可能)评估
    y+y
  • 我能想到的写它的最有效的方法是使用三元表达式

    x = (z == 3) ? y + y : y;
    

    这必须是至少两个操作(可能是3个)

  • 评估
    z==3
  • 分配给
    x
  • (可能)评估
    y+y
  • 我能想到的写它的最有效的方法是使用三元表达式

    x = (z == 3) ? y + y : y;
    
    写:

    (或其他任何你编辑你的问题到下一个)并激活你的编译器。这就是编译器的用途。你可以用编译器开关说出你想要的,编译器会比你做得更好

    写:

    if ( z == 3 )
        x = y * 2;
    else
        x = y;
    

    (或其他任何你编辑你的问题到下一个)并激活你的编译器。这就是编译器的用途。你可以用编译器开关说出你想要的,编译器会比你做得更好

    在二的补码上,表达式:

    (y * (z == 3)) 
    
    同:

    (y & -(z == 3))
    
    然而,两者的表现是否会明显不同,这是值得怀疑的。考虑下面的代码用<代码> gcc-o3-s < /> >:

    int foo1 (int y, int z) { return y * (z == 3); }
    int foo2 (int y, int z) { return y & -(z == 3); }
    int foo3 (int y, int z) { if (z == 3) return y; else return 0; }
    
    对于
    foo1()

    对于
    foo2()
    ,还有一条指令(尽管可能更便宜):

    但是,对于
    foo3()
    ,您可以得到:

        xorl    %eax, %eax
        cmpl    $3, 8(%esp)
        cmove   4(%esp), %eax
    

    尽管它是一条条件移动指令,但代码并没有比这更紧凑。

    在二的补码中,表达式:

    (y * (z == 3)) 
    
    同:

    (y & -(z == 3))
    
    然而,两者的表现是否会明显不同,这是值得怀疑的。考虑下面的代码用<代码> gcc-o3-s < /> >:

    int foo1 (int y, int z) { return y * (z == 3); }
    int foo2 (int y, int z) { return y & -(z == 3); }
    int foo3 (int y, int z) { if (z == 3) return y; else return 0; }
    
    对于
    foo1()

    对于
    foo2()
    ,还有一条指令(尽管可能更便宜):

    但是,对于
    foo3()
    ,您可以得到:

        xorl    %eax, %eax
        cmpl    $3, 8(%esp)
        cmove   4(%esp), %eax
    
    尽管这是一条有条件的移动指令,但代码并没有变得比这更紧凑。

    简易方法

    x = (z == 3) ? y : x;
    
    复杂方式

    x = y & (-(z == 3)); // Based on -1 = 1111...11 binary
    
    捷径

    x = (z == 3) ? y : x;
    
    复杂方式

    x = y & (-(z == 3)); // Based on -1 = 1111...11 binary
    


    你说的是“将采取”而不是“确实采取”。您是否查看了生成的程序集以进行确认?
    z==3
    将解析为布尔值,因此它将是0或1,因此结果将是y或0。根据平台的不同,条件可能更好。例如,大多数ARM指令都是有条件的,编译器可以利用这一点。此外,就像前面提到的@ddriver一样,如果
    z
    不是3,那么
    x
    将设置为0。这是您想要的吗?您指定的体系结构上的整数ALU操作应该需要1个单周期。-第60页你说的是“将采取”而不是“确实采取”。您是否查看了生成的程序集以进行确认?
    z==3
    将解析为布尔值,因此它将是0或1,因此结果将是y或0。根据平台的不同,条件可能更好。例如,大多数ARM指令都是有条件的,编译器可以利用这一点。此外,就像前面提到的@ddriver一样,如果
    z
    不是3,那么
    x
    将设置为0。这是您想要的吗?您指定的体系结构上的整数ALU操作应该需要1个单周期。-第60页我以前见过在这样的事情中使用三元表达式-我不明白为什么它们不引起分支?(我还以为它们只是IF-ELSE语句的语法糖。)三元表达式实际上不会给出相同的结果-当
    z==3
    为false时,OP的表达式将
    x
    设置为零,但你的表达式不会改变
    x
    ,这取决于情况,但很可能你的三元表达式不会导致@DrewMcGowen分支,如果你是正确的,我编辑了三元表达式。哦,我刚刚编辑了我的Q,因为你让我意识到了一些事情,但是不要担心,谢谢你的回答。我以前见过三元表达式在这样的事情中使用过——我不明白为什么它们不引起分支?(我还以为它们只是IF-ELSE语句的语法糖。)三元表达式实际上不会给出相同的结果-当
    z==3
    为false时,OP的表达式将
    x
    设置为零,但你的表达式不会改变
    x
    ,这取决于情况,但很可能你的三元表达式不会导致@DrewMcGowen分支,如果你是正确的,我编辑了三元表达式。哦,我只是编辑了我的Q,因为你让我意识到了一些事情,但不用担心,谢谢你的回答。是的,但它将
    x
    设置为
    y
    2y
    ,这与问题本身形成对比(当然,这是OP的问题,不是你的)。是的,但它将
    x
    设置为
    y
    2y
    ,这与问题本身形成对比(当然,这是OP的问题,不是你的问题)。