将 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 排除在外,因为它慢得多。

  1. 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. 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

  1. 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.

慢那么多