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

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

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

  1. 如果您有大量数据要进行字节交换,请仅使用此选项。
  2. 您应该认真考虑在托管C ++中编写最低级别的应用程序I / O,这样您就可以在将数据导入托管arrays之前进行交换。 您已经必须编写一个C ++库,因此没有太多损失,您可以回避在大型数据集上运行的低复杂性算法的所有与P / Invoke相关的性能问题。

PS:很多人都不知道字节交换内在函数。 它们的性能令人惊讶,对于浮点数据来说是双倍的,因为它将它们作为整数处理。 如果不为每个单字节交换用例手动编码寄存器负载,就没有办法击败它,如果你尝试这样做,你可能会在优化器中产生比你接下来更大的命中。

您可能只想重新考虑问题,这不应该成为瓶颈。 采用天真的算法(用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条指令是执行时间的重要组成部分,那么您正在执行非常高性能的任务,并且应该以正确的格式输入您的输入! 您也可能不会使用托管语言,因为您需要更多地控制数据缓冲区和什么不是,并且没有额外的数组边界检查。

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

我在考虑将两种uint类型视为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。