整数类型的 std::swap 有多快
How fast is std::swap for integer types?
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);
}
但是,有一种异或交换算法可以交换 2 个整数 (http://en.wikipedia.org/wiki/XOR_swap_algorithm(:
void swap_u( size_t& x, size_t& y )
{
x = x^y;
y = x^y;
x = x^y;
}
我的问题:
- 现在是优化吗(
x86
或arm
(? - C++标准是否支持这种优化?
- 在野外是否有任何真正的 STL 实现对整数具有
std::swap
专用化?
在绝大多数情况下,异或交换不是一种优化。
请参阅此维基条目。
在大多数实际场景中,使用临时寄存器的简单交换算法效率更高。异或交换可能实用的有限情况包括:
- 在指令集编码允许以较少的字节数编码 XOR 交换的处理器上;
在寄存器- 压力较高的区域中,它可能允许寄存器分配器避免溢出寄存器。
- 在可用RAM非常有限的微控制器中。
由于这些情况很少见,因此大多数优化编译器不会生成异或交换代码。
另请注意,异或交换的实现已损坏。您需要首先检查 x 和 y 是否没有别名。此检查肯定会使异或交换变慢。
我不知道有任何使用异或交换的标准库实现。
请注意,无论标准库实现什么,如果 XOR 交换确实比普通交换快,那么优化编译器将执行窥视孔优化以将其转换为 XOR 交换。这实际上是一个让编译器为您选择的情况。
或交换实际上只是一个噱头,在某些情况下可能会失败(例如,两个变量都是对同一对象的引用(。
异或交换也不是特别有效,因为它具有串行依赖关系,因此始终需要至少三个指令周期。使用带有临时的直接交换具有较少的依赖关系,允许在现代超标量CPU上进行一些并行性 - 在某些CPU上,它甚至可以在一个指令中实现,但即使没有特殊指令,它也可能在两个周期内执行。
在 X86 上,内存位置(不是 CPU 寄存器(之间的三重 XOR 交换与三重副本占用相同的处理器周期。如果临时是寄存器,它们可能会更少。
正如在大多数情况下已经解释的那样,异或位拨弄会更慢。
但它也在很大程度上取决于周围的代码。假设此交换是单独完成的,远离需要这些值的任何其他代码(因此它们不会加载到寄存器中(,我们在这里使用"普通"x86 处理器。
任何交换 2个值的算法至少需要 2 个操作将值从内存加载到寄存器中,另外需要 2 个操作将这些值再次存储到内存中(x86 没有直接交换 2 个内存位置内容的操作(。
使用这样的临时变量时:
void swap (int& a, int& b)
{
int temp = a;
a = b;
b = temp;
}
基本上,任何编译器都会认识到"temp"仅在本地用于交换,并且不会为其提供内存位置。由于它只保存"a"的值,因此它甚至不会是一个单独的寄存器。
它的汇编代码将如下所示(伪汇编(:
load a to rA
load b to rB
store rA to b
store rB to a
因此,在大多数情况下,就内存访问、指令数和寄存器数而言,这将是最有效的。
只有当编译器无法识别"temp"不用于其他任何内容并将其存储在单独的寄存器中(或被该死的精算内存(时,XOR 变体才能在任何方面更有效率。
但这仍然是理论上的,因为您的交换将被其他代码包围,这在那里将更为重要。如果这些值未被使用,则整个交换将被忽略。如果这些值直接用于其他计算,那么可能只是以下代码交换了 2 个寄存器,因此交换它本身有 0 条指令。而且您将很难找到任何比无所事事更有效的解决方案。
当然,还有其他更晦涩难懂的指令集可能具有直接交换 2 个内存位置内容的指令。
- 如何反转整数参数包
- enum是C++中的宏变量还是整数变量
- 努力将整数转换为链表。不知道我在这里做错了什么
- 整数不会重复超过随机数
- 在C++中手动调整数组大小
- 检查输入是否不是整数或数字
- C++使用整数的压缩数组初始化对象
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 将"打开的CV图像"中的"颜色"转换为整数格式
- 通过套接字[TCP]传输数据 如何在C / C ++中打包多个整数并使用send() recv()传输数据
- 如何只允许用户输入正整数
- 如何在c++中从文本文件中逐行读取整数
- C++:如何循环通过向量中的整数元素
- 我可以信任表示整数的浮点或双精度来保持精度吗
- 序列化,没有库的整数,得到奇怪的结果
- 在一定长度后从数组中打印时缺少整数
- std::当在256字节边界上写入整数时,流的奇怪行为
- 内联程序集printf将整数解释为地址
- 是否基于数组B整数打印数组A中的整数
- 整数类型的 std::swap 有多快