Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.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++ 整数类型的std::swap有多快?_C++_Performance_C++11_Stl_Swap - Fatal编程技术网

C++ 整数类型的std::swap有多快?

C++ 整数类型的std::swap有多快?,c++,performance,c++11,stl,swap,C++,Performance,C++11,Stl,Swap,STL实现了一个通用的std::swap函数来交换2个值。它可以用以下方式表示: template <class T> void swap (T& a, T& b) { T c(std::move(a)); a=std::move(b); b=std::move(c); } 我的问题: 它现在是一种优化(在x86或arm上) C++标准有利于这种优化吗? 在野外是否有真正的STL实现对整数进行了std::swap专门化 在绝大多数情况下,异或交换不是一种

STL实现了一个通用的
std::swap
函数来交换2个值。它可以用以下方式表示:

template <class T> void swap (T& a, T& b)
{
  T c(std::move(a));
  a=std::move(b);
  b=std::move(c);
}
我的问题:

  • 它现在是一种优化(在
    x86
    arm
    上)
  • C++标准有利于这种优化吗?
  • 在野外是否有真正的STL实现对整数进行了
    std::swap
    专门化

  • 在绝大多数情况下,异或交换不是一种优化

    看这个

    在大多数实际场景中,使用临时寄存器的简单交换算法更有效。XOR交换可能实用的有限情况包括:

    • 在处理器上,指令集编码允许以较小的字节数对异或交换进行编码
    • 在寄存器压力较高的区域,它可能允许寄存器分配器避免溢出寄存器
    • 在微控制器中,可用RAM非常有限
    因为这些情况很少发生,所以大多数优化编译器不会生成XOR交换代码

    还请注意,XOR交换的实现已中断。您需要首先检查x和y是否没有别名。此检查肯定会使XOR交换变慢

    我不知道有任何使用XOR交换的标准库实现


    请注意,无论标准库实现了什么,如果XOR交换确实比普通交换快,那么优化编译器会将其转换为XOR交换。这实际上是让编译器为您选择的情况。

    异或交换实际上只是一个噱头,在某些情况下可能会失败(例如,两个变量都是对同一对象的引用)


    XOR交换也不是特别有效,因为它具有串行依赖性,所以它总是至少需要三个指令周期。使用带有临时变量的直接交换具有较少的依赖性,允许在现代超标量CPU上实现一些并行性-在某些CPU上,它甚至可以在一条指令中实现,但即使没有特殊指令,它也可以在两个周期内执行。

    在X86上,内存位置(而不是CPU寄存器)之间的三重异或交换采用与三重拷贝相同的处理器周期。如果临时寄存器是一个寄存器,它们可能会更少。

    正如已经在大多数场景中解释的那样,异或位篡改将更慢

    但这也在很大程度上取决于周围的代码。 假设这个交换是单独完成的,远离需要这些值的任何其他代码(因此它们不会加载到寄存器中),我们在这里使用的是“普通”x86处理器

    任何交换2个值的算法都至少需要2个操作将值从内存加载到寄存器中,并需要另外2个操作将这些值再次存储到内存中(x86没有直接交换2个内存位置内容的操作)

    使用这样的临时变量时:

    void swap (int& a, int& b)
    {
      int temp = a;
      a = b;
      b = temp;
    }
    
    基本上,任何编译器都会认识到“temp”只在本地用于交换,不会给它一个内存位置。 因为它只保存“a”的值,所以它甚至不是一个单独的寄存器

    其汇编代码如下所示(伪汇编):

    因此,在大多数情况下,就内存访问、指令数量和寄存器数量而言,这可能是最有效的

    只有当编译器无法识别“temp”不用于任何其他用途,并将其存储在单独的寄存器(或该死的实际内存)中时,XOR变量才能在任何方面更有效

    但这仍然是理论上的,因为您的交换将被其他代码包围,而这将非常重要。如果不再使用这些值,则整个交换将被忽略。如果这些值直接用于其他计算,那么可能只是以下代码交换了2个寄存器,因此交换本身就有0条指令。你将很难找到比无所事事更有效的解决方案


    当然,还有其他更模糊的指令集,可能有指令直接交换2个内存位置的内容。

    XOR交换不一定有效-与其说是一种有用的优化,不如说是一种新颖-只需使用一个临时变量,保持简单,避免噱头-让编译器做一些聪明的事情。如果x和y指向同一个内存地址,第二个实现将不起作用(如果传递具有可变索引的数组元素,可能会发生这种情况)智能编译器了解std::swap正在做什么,并且可以简单地注意到变量可以在不同的寄存器或地址中引用。这是一种有效的无成本互换。如果查看生成的程序集,您可以看到这一点。这里有一个重要的教训:某些东西看起来很复杂和粗糙,并不意味着它会更快。:)@这甚至不需要(总是)理解
    std::swap
    的编译器,甚至也不需要非常智能的编译器——不必要的寄存器移动通常可以通过相当简单的窥视孔优化和寄存器调度来消除。(另一方面,XOR技巧需要一个更聪明的编译器来优化)。我们在这里学到了一个很好的教训:异常棘手的wiki代码不可能是优化
    void swap (int& a, int& b)
    {
      int temp = a;
      a = b;
      b = temp;
    }
    
    load a to rA
    load b to rB
    store rA to b
    store rB to a