代码之家  ›  专栏  ›  技术社区  ›  willeM_ Van Onsem

ASM中的快速小端到大端转换

  •  5
  • willeM_ Van Onsem  · 技术社区  · 17 年前

    我在C#中有一个uint类型数组,在检查程序是否在一个小的endian机器上工作后,我想将数据转换为一个大的endian类型。因为数据量可以变得非常大,但总是是均匀的,所以我想考虑两种UITE类型作为ULUN类型,为了更好的性能并在ASM中编程,所以我正在寻找一种非常快(最快的,如果可能的)汇编算法来转换大Endiad中的小字节。

    3 回复  |  直到 16 年前
        1
  •  8
  •   Sam Harwell    17 年前

    对于大量数据 bswap 指令(在VisualC++中可用) _byteswap_ushort , _byteswap_ulong , and _byteswap_uint64 内在的)是一条路要走。这甚至会比手写汇编更好。如果没有P/Invoke,这些在纯C#中不可用,因此:

    1. 如果你有,就用这个 很多 数据到字节的交换。

    PS:很多人都不知道字节交换的本质。它们的性能是惊人的,浮点数据的性能是惊人的两倍,因为它将它们作为整数处理。如果不为每一个单字节交换用例手工编码寄存器负载,就没有办法打败它,如果您尝试这样做,您可能会在优化器中受到比您所得到的更大的影响。

        2
  •  2
  •   RH.    16 年前

    你可能想简单地重新思考这个问题,这不应该是一个瓶颈。以naive算法为例(用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
  •  1
  •   Guffa    17 年前

    我在考虑考虑两个问题。 类型作为ulong类型

    您可以在不安全的模式下尝试一些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。