ASM中快速的little-endian到big-endian转换

时间:2009-08-31 18:27:37

标签: c# algorithm assembly endianness performance

我在C#中有一个uint类型数组,在检查程序是否在小端机器上运行之后,我想将数据转换为big-endian类型。因为数据量可能变得非常大但总是均匀,我想考虑将两种uint类型作为ulong类型,以获得更好的性能并在ASM中对其进行编程,因此我搜索的速度非常快(如果可能的话,速度最快) )汇编程序算法,用于转换big-endian中的little-endian。

3 个答案:

答案 0 :(得分:6)

对于大量数据,bswap指令(在_byteswap_ushort, _byteswap_ulong, and _byteswap_uint64内在函数下的Visual C ++中可用)是可行的方法。这甚至会超过手写组装。没有P / Invoke的纯C#中没有这些,所以:

  1. 如果你有很多的数据来进行字节交换,那么只能使用它。
  2. 您应该认真考虑在托管C ++中编写最低级别的应用程序I / O,以便在将数据导入托管阵列之前进行交换。您已经必须编写一个C ++库,因此没有太多损失,您可以回避在大型数据集上运行的低复杂度算法的所有与P / Invoke相关的性能问题。
  3. PS:很多人都不知道字节交换内在函数。它们的性能令人惊讶,对于浮点数据来说是双倍的,因为它将它们作为整数处理。如果没有手动编码每个单字节交换用例的寄存器负载,就没有办法击败它,如果你尝试这样做,你可能会在优化器中产生比你接下来更大的命中。

答案 1 :(得分:2)

您可能只想重新考虑问题,这不应该成为瓶颈。采用天真的算法(用CLI汇编编写,只是为了好玩)。假设我们想要的数字是本地数字0

LDLOC 0
SHL 24
LDLOC 0
LDC.i4 0x0000ff00
SHL 8
OR
LDLOC 0
LDC.i4 0x00ff0000
SHL.UN 8
OR
LDLOC 0
SHL.UN 24
OR

每个数字最多只有13(x86)个汇编指令(通过使用聪明的寄存器,解释器很可能更智能)。它并没有比那更天真。

现在,将其与

的成本进行比较
  • 加载数据(包括您正在使用的外围设备!)
  • 数据的Maniuplation(例如,比较)
  • 输出结果(无论是什么)

如果每个数字的13个指令是执行时间的重要组成部分,那么您正在执行非常高性能的任务,并且应该以正确的格式输入您的输入!您也可能不会使用托管语言,因为您需要更多地控制数据缓冲区和什么不是,并且没有额外的数组边界检查。

如果该数据数据来自网络,我预计管理套接字的成本会比单纯的字节顺序翻转要大得多,如果它来自磁盘,则考虑在执行此程序之前预先翻转。 / p>

答案 2 :(得分:1)

  我想考虑两个因素   类型为ulong类型

那么,这也会交换两个uint值,这可能是不可取的......

您可以在不安全模式下尝试一些C#代码,这可能实际上表现得足够好。像:

public static unsafe void SwapInts(uint[] data) {
   int cnt = data.Length;
   fixed (uint* d = data) {
      byte* p = (byte*)d;
      while (cnt-- > 0) {
         byte a = *p;
         p++;
         byte b = *p;
         *p = *(p + 1);
         p++;
         *p = b;
         p++;
         *(p - 3) = *p;
         *p = a;
         p++;
      }
   }
}

在我的计算机上,吞吐量大约为每秒2 GB。