在C#中,如何更快地将ulong[64]转换为byte[512]?

4
我有一种方法可以使用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]);
                }

1
可能有助于发布您想要更高效的代码。 - Sam Holder
我认为这是一个有趣的问题,因为在使用其他语言的DLL时,这是一个普遍存在的问题。 - BlueTrin
4个回答

4
unsafe 
{
    fixed (ulong* src = ulongs) 
    {
        Marshal.Copy(new IntPtr((void*)src), bytes, 0, 512);
    }
}

这似乎有效。我不确定是否需要“fixed”,但在定时测试中失去了整整一秒钟。

需要使用fixed语句,因为它可以防止垃圾回收器重新定位可移动变量。如果没有fixed,你的代码甚至无法编译。 - Igor Korkhov
而且你的版本比我的表现更好,很棒你提醒了我使用 Marshal.Copy(),谢谢! - Igor Korkhov

3

可能最快的方法是使用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语句的方法,只需要一个未经管理的转换(这些是我能想到的最好的词来描述我正在寻找的东西)。 - Corey Ogburn
你可以通过在for()循环语句体内编写类似于"byte[i] = *(pb + i); byte[i+1] = *(pb + i+1); byte[i+2] = *(pb + i+2); ...; byte[i+7] = *(pb + i +7);"的代码来展开for()循环。 - Igor Korkhov

0
使用System.Buffer辅助类。
ulong[] buffer = null;
int byteLength = Buffer.ByteLength(buffer);
byte[] byteBuffer = new byte[byteLength];
Buffer.BlockCopy(buffer, 0, byteBuffer, 0, byteLength);

0
您可以使用 struct 和显式布局指令,使用 StructLayout 属性来强制变量占用相同的空间,从而实现此目的。
这样,您可以使用 ulong 属性编写值,并使用 byte 数组属性读取该值。当然,这假定 byte 数组确实占用了您所期望的空间,并且它没有使用 32 位来存储 8 位信息。我将在规范中查找这一点,但我还没有完成。

不行,byte[] 数组里还有其他信息,所以当你试图加载这种类型时会出现错误,因为它包含一个偏移量为0的对象字段,该字段被错误地对齐或与非对象字段重叠。 - chris.w.mclean
如果您知道该字段的大小,那么您可能可以适当地偏移ulong。 - Jeff Yates

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接