【问题标题】:Fast little-endian to big-endian conversion in ASMASM 中小端到大端的快速转换
【发布时间】:2009-08-31 18:27:37
【问题描述】:

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

【问题讨论】:

  • 至少 1'000'000 uints(也许少一点,但可以变大)

标签: c# algorithm assembly endianness performance


【解决方案1】:

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

  1. 仅当您有 大量 数据要进行字节交换时才使用此选项。
  2. 您应该认真考虑使用托管 C++ 编写最低级别的应用程序 I/O,以便在将数据放入托管数组之前进行交换。您已经必须编写一个 C++ 库,因此没有什么可失去的,并且您可以回避所有与 P/Invoke 相关的性能问题,以便在大型数据集上运行低复杂度算法。

PS:许多人不知道字节交换内在函数。它们的性能令人惊讶,对于浮点数据更是如此,因为它将它们作为整数处理。如果不对每个单字节交换用例的寄存器负载进行手动编码,就无法击败它,如果您尝试这样做,您可能会在优化器中受到比您所接受的更大的打击。

【讨论】:

    【解决方案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) 汇编指令(而且解释器很可能会通过使用聪明的寄存器变得更加智能)。没有比这更天真的了。

    现在,将其与成本进行比较

    • 获取加载的数据(包括您正在使用的任何外围设备!)
    • 数据处理(例如进行比较)
    • 输出结果(不管是什么)

    如果每个数字 13 条指令占您执行时间的很大一部分,那么您正在执行一项非常高性能的任务,并且应该以正确的格式输入!您也可能不会使用托管语言,因为您希望对数据缓冲区和其他内容进行更多控制,并且不需要额外的数组边界检查。

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

    【讨论】:

      【解决方案3】:

      我在考虑考虑两个 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。

      【讨论】:

        猜你喜欢
        • 2016-02-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-17
        • 2014-05-24
        • 1970-01-01
        相关资源
        最近更新 更多