使用Buffer.BlockCopy将数组ushort[]转换为int[]



我正在尝试将值为0-65k的ushort[4k*4k]数组类型转换为相同值的int[]数组类型。

似乎看到了缓冲区。BlockCopy是最快的方法。我正在尝试以下代码:

   ushort[] uPixels = MakeRandomShort(0, 65000, 4000 * 4000);// creates ushort[] array
   int[] iPixels = new int[4000 * 4000];
   int size = sizeof(ushort);
   int length = uPixels.Length * size;
   System.Buffer.BlockCopy(uPixels, 0, iPixels, 0, length);

但是iPixels在非常奇怪的范围内存储了一些奇怪的值+-1411814783,+- 2078052064等

出了什么问题,我需要做什么才能使它正常工作?

谢谢!

GitHub上有一个相关的讨论

ushort[]复制到int[]数组不能用于为连续内存范围调优的例程。

基本上,您必须清除目标int细胞的上半部分。然后,需要某种(并行的?)循环来复制实际数据。

有可能使用指针以两个字节为步进的不安全代码。缓冲区的实现。BlockCopy在Microsoft源代码存储库中不可见。寻找源代码并修改它可能是有意义的。


更新

我实现了两个C++函数,并与C#循环副本进行了粗略的性能测量。

c#实现

const int LEN = 4000 * 4000;
for (int i = 0; i < LEN; i++)
{
    iPixels[i] = uPixels[i];
}

c++实现SpeedCopy1

// Copy loop with casting from unsigned short to int
__declspec(dllexport) void SpeedCopy1(unsigned short *uArray, int * iArray, int len)
{
    for (int i = 0; i < len; i++)
    {
        *iArray++ = *uArray++;
    }
}

c++实现SpeedCopy2

/// Copy loop with unsigned shorts
/// Clear upper half of int array elements in advance
__declspec(dllexport) void SpeedCopy2(unsigned short* uArray, int* iArray, int len)
{
    unsigned short* up = (unsigned short*)iArray;
    memset(iArray, 0, sizeof(int) * len);
    for (int i = 0; i < len; i++)
    {
        *up = *uArray++;
        up += 2;
    }
}

得到的时间:

C# loop copy  27 ms
SpeedCopy1     9 ms
SpeedCopy2    18 ms

与c#循环相比,外部c++函数可以将复制时间减少三分之一。
使用多线程能获得什么样的效果还有待观察。

相关内容

  • 没有找到相关文章

最新更新