3

次に、System.Buffer.BlockCopyを使用してプリミティブの配列に変換されるバイト配列が渡されます。基本的に私のコードは次のようになります。

    void Convert(byte[] b)
    {
        int[] i1 = new int[100];    // real arrays much larger
        double[] d1 = new double[100];
        int iPos=0, iSize;

        iSize = i1.Length * sizeof(int);
        System.Buffer.BlockCopy(b, iPos, i1, 0, iSize);
        iPos += iSize;

        iSize = d1.Length * sizeof(double);
        System.Buffer.BlockCopy(b, iPos, d1, 0, iSize);
        iPos += iSize;

        //etc: lots of arrays

        b=null;         
    }

これは非常にパフォーマンスが高いですが、bが解放されるまで、メモリ使用量は明らかに私のバイト配列の2倍のサイズです。

バイト配列のセクションをプリミティブ配列に直接キャストする方法はありますか?データのコピーを伴わない(したがって、メモリ使用量が2倍にならない)もので、おそらくさらに高速ですか?

4

3 に答える 3

3

安全でないコードを使用することができます(使用が許可されている場合は使用しません)。ただし、次のようなものを試すことができます(余分な配列を使用する必要はなく、バイトの配列のみを使用します)。

    unsafe public void Convert(void* b)
    {
        int i;

        double* asDouble = (double*)b;
        double sum1 = 0.0;
        for (i = 0; i < 100; i++, asDouble++)
            sum1 += *asDouble;

        int* asInt = (int*)asDouble;
        int sum2 = 0;
        for (i = 0; i < 100; i++, asInt++)
            sum2 += *asInt;
    }

    public unsafe void SomeThing()
    {
        byte[] rawbytes = new byte[44000];

        // Fill the "rawbytes" array somehow

        fixed (byte* ptr = rawbytes)
        {
            Convert(ptr);
        }
    }
于 2013-01-08T20:55:15.450 に答える
0

安全でないコードを使用する可能性があります。ユニオンを使用した1つの解決策(あなたの状況には当てはまらないもの)

namespace TestApplication
{
    using System;
    using System.Runtime.InteropServices;

    internal static class Program
    {
        private static unsafe void Main()
        {           
            var x = new ByteDoubleUnion();

            x.bytes[0] =  24;
            x.bytes[1] =  45;
            x.bytes[2] =  68;
            x.bytes[3] =  84;
            x.bytes[4] = 251;
            x.bytes[5] =  33;
            x.bytes[6] =   9;
            x.bytes[7] =  64;

            // Prints pi.
            Console.WriteLine(x.doubleValue);

            Console.ReadLine();
        }
    }

    [StructLayout(LayoutKind.Explicit)]
    internal unsafe struct ByteDoubleUnion
    {
        [FieldOffset(0)]
        internal Double doubleValue;

        [FieldOffset(0)]
        internal fixed Byte bytes[8];
    }
}

1つの解決策は、ポインタをキャストするだけです。

namespace TestApplication
{
    using System;

    internal static class Program
    {
        private static unsafe void Main()
        {           
            var bytes = new Byte[] { 24, 45, 68, 84, 251, 33, 9, 64 };

            fixed (Byte* p = &bytes[0])
            {
                // Prints pi, too.
                Console.WriteLine(*((Double*)p));
            }

            Console.ReadLine();
        }
    }
}
于 2013-01-08T21:16:31.807 に答える
0

これは、配列の結合された構造を使用した試みです(他の投稿の構造体の配列とは異なります)。これは、より高速である必要があるためです。

[StructLayout(LayoutKind.Explicit)]
public unsafe struct ByteBuffer
{        
    public const int IntSize=10;
    public const int DoubleSize=5;
    public const int IntBytes=sizeof(int)*IntSize;
    public const int DoubleBytes=sizeof(double)*DoubleSize;

    // Int array is unioned with byte array
    [FieldOffset(0)]
    fixed int int_array[IntSize];
    [FieldOffset(0)]
    fixed byte int_array_bytes[IntBytes];

    // Double array us unioned with byte array
    [FieldOffset(IntBytes)]
    fixed double double_array[DoubleSize];
    [FieldOffset(IntBytes)]
    fixed byte double_array_bytes[DoubleBytes];

    // Take array of bytes and distribute it 
    // by byte to each array
    public ByteBuffer(byte[] b)
    {
        fixed(byte* ptr=int_array_bytes)
        {
            for(int i=0; i<IntBytes; i++)
            {
                ptr[i]=b[i];
            }
        }
        fixed(byte* ptr=double_array_bytes)
        {

            for(int i=0; i<DoubleBytes; i++)
            {
                ptr[i]=b[IntBytes+i];
            }
        }
    }
    // Convert unmanaged array to managed array
    public int[] ToIntArray()
    {
        int[] result=new int[IntSize];
        fixed(int* ptr=int_array)
        {
            for(int i=0; i<IntSize; i++)
            {
                result[i]=ptr[i];
            }
        }
        return result;
    }
    // Convert unmanaged array to managed array
    public double[] ToDoubleArray()
    {
        double[] result=new double[DoubleSize];
        fixed(double* ptr=double_array)
        {
            for(int i=0; i<DoubleSize; i++)
            {
                result[i]=ptr[i];
            }
        }
        return result;
    }
}

class Program
{
    static void Main(string[] args)
    {
        // Load up with test data
        byte[] data=new byte[..];
        // I tested with 10 ints and 5 doubles encoded into bytes

        //Now to test the Fast conversion
        ByteBuffer bb=new ByteBuffer(data);
        int[] data1=bb.ToIntArray();
        double[] data2=bb.ToDoubleArray();
    }
}
于 2013-01-08T21:54:21.660 に答える