我正在尝试将值为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++函数可以将复制时间减少三分之一。
使用多线程能获得什么样的效果还有待观察。