我传递了一个字节数组,然后使用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;
}
这是非常高效的,但它的内存使用量明显是我的字节数组的2倍,直到b被释放。
有没有办法直接将字节数组的部分转换为原始数组?一个不涉及复制数据(因此不会使内存使用量增加一倍),并且可能更快?
答案 0 :(得分: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);
}
}
答案 1 :(得分:0)
可以使用不安全的代码。使用联合的一种解决方案(我的情况不适用)
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];
}
}
和一个解决方案只是投射指针。
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();
}
}
}
答案 2 :(得分:0)
这是一个使用联合数组结构的尝试(与其他帖子中的struct数组不同),因为这应该更快。
[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();
}
}