【问题标题】:In C#, convert ulong[64] to byte[512] faster?在 C# 中,将 ulong[64] 转换为 byte[512] 更快?
【发布时间】:2010-01-25 16:41:48
【问题描述】:

我有一种方法可以在 for 语句中使用二进制移位将 ulong 转换为字节,但它的时间效率不是很高。有没有办法将大小为 64 的 ulong 数组直接转换为大小为 512 的字节数组?这是一段运行数千次的代码,我需要每毫秒保存一次,这样我才能反过来节省秒数。

编辑: 现在这就是我正在做的事情:

                for (int k = 0; k < ulongs.Length; k++) {
                    bytes[(k << 3)] = (byte)(ulongs[k] >> 56);
                    bytes[(k << 3) + 1] = (byte)(ulongs[k] >> 48);
                    bytes[(k << 3) + 2] = (byte)(ulongs[k] >> 40);
                    bytes[(k << 3) + 3] = (byte)(ulongs[k] >> 32);
                    bytes[(k << 3) + 4] = (byte)(ulongs[k] >> 24);
                    bytes[(k << 3) + 5] = (byte)(ulongs[k] >> 16);
                    bytes[(k << 3) + 6] = (byte)(ulongs[k] >> 8);
                    bytes[(k << 3) + 7] = (byte)(ulongs[k]);
                }

【问题讨论】:

  • 发布您想要提高效率的代码可能会有所帮助。
  • 我认为这是一个有趣的问题,因为这是使用其他语言 DLL 时的普遍问题。

标签: c# optimization


【解决方案1】:
unsafe 
{
    fixed (ulong* src = ulongs) 
    {
        Marshal.Copy(new IntPtr((void*)src), bytes, 0, 512);
    }
}

这似乎有效。我不确定是否需要修复,但我在计时测试中损失了一秒。

【讨论】:

  • Fixed 是必需的,因为 fixed 语句会阻止垃圾收集器重新定位可移动变量。如果不修复,您的代码甚至无法编译。
  • 你的版本比我的好,你让我想起了 Marshal.Copy() 真是太好了,谢谢!
【解决方案2】:

可能最快的方法是使用unsafefixed 构造。这是一个例子:

ulong[] ulongs = new ulong[64];
byte[] bytes = new byte[512];

unsafe
{
    fixed (ulong* src = ulongs)
    {
        byte* pb = (byte*)src;
        for (int i = 0; i < bytes.Count(); i++)
        {
             bytes[i] = *(pb + i);
        }
    }
}

在编译上述代码时,请不要忘记使用/unsafe编译器开关。

编辑:这是第一个代码片段的修改版本,它在我的机器上运行得更快:

unsafe
{
    fixed (ulong* src = ulongs)
    {
        fixed (byte *dst = bytes)
        {
            ulong* pl = (ulong*)dst;
            for (int i = 0; i < ulongs.Count(); i++)
            {
                *(pl + i) = *(src + i);
            }   
        }
    }
}

【讨论】:

  • 我试过这段代码,当我的程序通常运行在 3.5 秒时,它跳到了 8.5 秒。我对此寄予厚望,但我正在寻找一种不包括 for 语句的方法,只是一个非托管演员表(这些是我能想到的最好的词来称呼我正在寻找的东西)
  • 您可以通过编写类似“byte[i] = *(pb + i); byte[i+1] = *(pb + i+1); byte[ i+2] = *(pb + i+2); ...; 字节[i+7] = *(pb + i +7);"在 for() 语句体中
【解决方案3】:

您可以使用struct 和使用StructLayout 属性强制变量占据相同空间的显式布局指令来实现此目的。

这样您就可以使用ulong 属性写入值并使用byte 数组属性读取它。当然,这假设 byte 数组确实占用了您期望的空间,并且它没有使用 32 位来保存 8 位信息。我必须在规范中查找,我还没有这样做。

【讨论】:

  • 不,byte[] 有一些其他信息,因此在尝试加载此类类型时会出现错误,因为它包含偏移量 0 处的对象字段,该对象字段未正确对齐或重叠对象字段。
  • 如果你知道那个字段的大小,你大概可以适当地偏移ulong。
【解决方案4】:

使用 System.Buffer 辅助类。

ulong[] buffer = null;
int byteLength = Buffer.ByteLength(buffer);
byte[] byteBuffer = new byte[byteLength];
Buffer.BlockCopy(buffer, 0, byteBuffer, 0, byteLength);

【讨论】:

    猜你喜欢
    • 2011-01-13
    • 2015-06-09
    • 1970-01-01
    • 1970-01-01
    • 2018-03-25
    • 2013-11-18
    • 1970-01-01
    • 1970-01-01
    • 2020-02-03
    相关资源
    最近更新 更多