将 int[] 转换为 short[],反之亦然
Converting int[] to short[] and vice versa
我正在尝试使用 Kinect for Xbox 360 和 SDK 1.8 计算玩家的表面积。我 运行 遇到了一个小问题,我需要将 short[]
转换为 int[]
,反之亦然。解释更多...
short[] rawDepthData = new short[depthFrame.PixelDataLength];
depthFrame.CopyPixelDataTo(rawDepthData);
但我需要 int[]
格式的 rawDepthData
..
感谢帮助
非常感谢
对于您可能希望尽可能快的事情,您可能需要考虑编写自己的循环以将 short[]
数组复制到新的 int[]
数组中,例如:
public static int[] Convert(short[] input)
{
int[] result = new int[input.Length];
for (int i = 0; i < input.Length; ++i)
result[i] = input[i];
return result;
}
以下是您转换回来的方式。重要提示:这假设 int
个值都适合 short
。否则,它们将被截断并且值将发生变化!
public static short[] Convert(int[] input)
{
short[] result = new short[input.Length];
unchecked
{
for (int i = 0; i < input.Length; ++i)
result[i] = (short) input[i];
}
return result;
}
(注意:将此代码的性能与 Array.ConvertAll()
的性能进行比较时,您必须将此代码编译为 RELEASE 版本 - 否则您会将调试版本与发布版本进行比较。)
您可以使用 Linq:
var myIntData = rawDepthData.Select(x => (int)x).ToArray();
或者只是一个 for
循环(这会快得多),如果您的目标是性能:
var myIntData = new int[rawDepthData.Length];
for(var i = 0; i < rawDepthData.Length; i++)
myIntData[i] = rawDepthData[i];
如果追求性能,我会使用 for
方法,并准备好我的 int[]
数组(而不是每次都分配一个新数组),因为原始深度数据长度是更有可能不会改变
另一种更高效的方法是使用 unsafe
、指针和展开循环:
unsafe static void CopyData(short[] input, int[] output)
{
fixed(short* pt1 = input)
fixed(int* pt2 = output)
{
short* pt1f = pt1;
int* pt2f = pt2;
for (int i = 0; i < input.Length/8; i ++)
{
*pt2f = *pt1f;
*(pt2f + 1) = *(pt1f + 1);
*(pt2f + 2) = *(pt1f + 2);
*(pt2f + 3) = *(pt1f + 3);
*(pt2f + 4) = *(pt1f + 4);
*(pt2f + 5) = *(pt1f + 5);
*(pt2f + 6) = *(pt1f + 6);
*(pt2f + 7) = *(pt1f + 7);
pt1f += 8;
pt2f += 8;
}
}
}
虽然对于 .NET 框架来说有点难看,但这应该是最快的方法。我实际上做了一些分析(无论如何都不科学),并且在我的一些测试中,使用不同的数组大小和循环,unsafe
增加了 ~30-40%(注意没有展开循环,我得到了大约 5-10% 的非常小的性能提升,具体取决于数组大小)...这实际上假设长度可以被 8 整除,您可以根据需要进行调整或检查:-)
分析
* 只是因为我很好奇,现在有点时间
出于好奇,这是我对不同方法进行一些分析的结果(100% 是最快的方法,"iterations" 是我进行复制操作的次数...我验证数据,但不在性能计算之内),而且,数组是预先分配的(不是在每次迭代时都分配)。我将 Linq 排除在外,因为它慢得多。
- 100,000 次迭代,数组长度为 80,000
Unsafe unrolled: 100% - 00:00:02.5536184
Simple for() loop: 70,88% - 00:00:03.6024272
foreach(...): 59,24% - 00:00:04.3105598
Unrolled for(): 38,26% - 00:00:06.6739715
- 1,000,000 次迭代,数组长度为 8,000
Unsafe unrolled: 100% - 00:00:02.3733392
Simple for() loop: 67,70% - 00:00:03.5055304
foreach(...): 55,00% - 00:00:04.3149544
Unrolled for(): 39,53% - 00:00:06.0041744
- 10,000 次迭代,数组长度为 800,000
Unsafe unrolled: 100% - 00:00:02.5565005
Simple for() loop: 73,69% - 00:00:03.4688333
foreach(...): 59,75% - 00:00:04.2783304
Unrolled for(): 39,46% - 00:00:06.4778782
我真的很惊讶安全"unrolled" for
是最昂贵的方法......想想看,这是有道理的,但乍一看(至少对我来说,来自 x86 汇编背景,在那些日子里展开循环以提高性能非常普遍)我从来没有这么说过。我也没想到 foreach
会比简单的 for
.
慢那么多
我正在尝试使用 Kinect for Xbox 360 和 SDK 1.8 计算玩家的表面积。我 运行 遇到了一个小问题,我需要将 short[]
转换为 int[]
,反之亦然。解释更多...
short[] rawDepthData = new short[depthFrame.PixelDataLength];
depthFrame.CopyPixelDataTo(rawDepthData);
但我需要 int[]
格式的 rawDepthData
..
感谢帮助 非常感谢
对于您可能希望尽可能快的事情,您可能需要考虑编写自己的循环以将 short[]
数组复制到新的 int[]
数组中,例如:
public static int[] Convert(short[] input)
{
int[] result = new int[input.Length];
for (int i = 0; i < input.Length; ++i)
result[i] = input[i];
return result;
}
以下是您转换回来的方式。重要提示:这假设 int
个值都适合 short
。否则,它们将被截断并且值将发生变化!
public static short[] Convert(int[] input)
{
short[] result = new short[input.Length];
unchecked
{
for (int i = 0; i < input.Length; ++i)
result[i] = (short) input[i];
}
return result;
}
(注意:将此代码的性能与 Array.ConvertAll()
的性能进行比较时,您必须将此代码编译为 RELEASE 版本 - 否则您会将调试版本与发布版本进行比较。)
您可以使用 Linq:
var myIntData = rawDepthData.Select(x => (int)x).ToArray();
或者只是一个 for
循环(这会快得多),如果您的目标是性能:
var myIntData = new int[rawDepthData.Length];
for(var i = 0; i < rawDepthData.Length; i++)
myIntData[i] = rawDepthData[i];
如果追求性能,我会使用 for
方法,并准备好我的 int[]
数组(而不是每次都分配一个新数组),因为原始深度数据长度是更有可能不会改变
另一种更高效的方法是使用 unsafe
、指针和展开循环:
unsafe static void CopyData(short[] input, int[] output)
{
fixed(short* pt1 = input)
fixed(int* pt2 = output)
{
short* pt1f = pt1;
int* pt2f = pt2;
for (int i = 0; i < input.Length/8; i ++)
{
*pt2f = *pt1f;
*(pt2f + 1) = *(pt1f + 1);
*(pt2f + 2) = *(pt1f + 2);
*(pt2f + 3) = *(pt1f + 3);
*(pt2f + 4) = *(pt1f + 4);
*(pt2f + 5) = *(pt1f + 5);
*(pt2f + 6) = *(pt1f + 6);
*(pt2f + 7) = *(pt1f + 7);
pt1f += 8;
pt2f += 8;
}
}
}
虽然对于 .NET 框架来说有点难看,但这应该是最快的方法。我实际上做了一些分析(无论如何都不科学),并且在我的一些测试中,使用不同的数组大小和循环,unsafe
增加了 ~30-40%(注意没有展开循环,我得到了大约 5-10% 的非常小的性能提升,具体取决于数组大小)...这实际上假设长度可以被 8 整除,您可以根据需要进行调整或检查:-)
分析
* 只是因为我很好奇,现在有点时间
出于好奇,这是我对不同方法进行一些分析的结果(100% 是最快的方法,"iterations" 是我进行复制操作的次数...我验证数据,但不在性能计算之内),而且,数组是预先分配的(不是在每次迭代时都分配)。我将 Linq 排除在外,因为它慢得多。
- 100,000 次迭代,数组长度为 80,000
Unsafe unrolled: 100% - 00:00:02.5536184
Simple for() loop: 70,88% - 00:00:03.6024272
foreach(...): 59,24% - 00:00:04.3105598
Unrolled for(): 38,26% - 00:00:06.6739715
- 1,000,000 次迭代,数组长度为 8,000
Unsafe unrolled: 100% - 00:00:02.3733392
Simple for() loop: 67,70% - 00:00:03.5055304
foreach(...): 55,00% - 00:00:04.3149544
Unrolled for(): 39,53% - 00:00:06.0041744
- 10,000 次迭代,数组长度为 800,000
Unsafe unrolled: 100% - 00:00:02.5565005
Simple for() loop: 73,69% - 00:00:03.4688333
foreach(...): 59,75% - 00:00:04.2783304
Unrolled for(): 39,46% - 00:00:06.4778782
我真的很惊讶安全"unrolled" for
是最昂贵的方法......想想看,这是有道理的,但乍一看(至少对我来说,来自 x86 汇编背景,在那些日子里展开循环以提高性能非常普遍)我从来没有这么说过。我也没想到 foreach
会比简单的 for
.