读取字节数组vs int数组和位移位-what';s更快

本文关键字:数组 更快 -what vs 字节 int 读取 字节数 | 更新日期: 2023-09-27 18:04:02

其中一个明显更快吗?

var scan0 = (uint*)bitmapData.Scan0;
int length = pixels.Length;
for (int i = 0; i < length; i++)
{
    uint j = scan0[i];
    float a = (j >> 24) / 255f;
    pixels[i] = new Vector(
        (j >> 16 & 0xff) * a / 255,
        (j >> 8 & 0xff) * a / 255,
        (j & 0xff) * a / 255);
}

var scan0 = (byte*)bitmapData.Scan0;
int length = pixels.Length * 4;
for (int i = 0; i < length; i += 4)
{
    float a = scan0[i + 3] / 255f;
    pixels[i / 4] = new Vector(
        scan0[i + 2] * a / 255,
        scan0[i + 1] * a / 255,
        scan0[i] * a / 255);
}

读取字节数组vs int数组和位移位-what';s更快

在32位应用程序中,第二个程序的速度大约是第一个程序的2.5倍。在64位应用程序中,第二个比第一个快大约25%。

请注意,第二段代码中有一个错误。当您在每次迭代中添加四个时,您将在pixels数组中的每四个项中放置对象,并在其用完数组时引发IndexOutOfRangeException异常。

比第二个稍快(约5%(的是移动每个像素的指针:

byte* scan0 = (byte*)bitmapData.Scan0;
for (int i = 0; i < pixels.Length; i++) {
  float a = scan0[3] / 255f;
  pixels[i] = new Vector(
    scan0[2] * a / 255,
    scan0[1] * a / 255,
    scan0[0] * a / 255
  );
  scan0 += 4;
}

还要注意,如果从Bitmap图像读取数据,则不会将其存储为像素数据的连续阵列。扫描线之间可能存在填充,因此代码只能从单个扫描线读取像素,无法安全地从整个图像读取数据。

编辑:

此外,我刚刚意识到,你把数组的长度放在一个变量中,并在循环中使用它。这只会使代码变得更慢而不是更快,因为编译器无法优化对数组访问的范围检查。

我认为"您的第一个解决方案"的移位更快。但是您可以使用Stopwatch对其进行测试。在调用该方法之前启动stopwatch,多次运行该方法,然后停止手表并检查其ElapcedMilliseconds。类似:

System.Diagnostics.Stopwatch watch = Stopwatch.StartNew();
//run your method that want to test its executable time multi time
for (int testIndex = 0; testIndex < 100; testIndex++)    
{ 
    TestWithShift(); 
}
watch.Stop();
Console.WriteLine("Test with shift time: {0}", watch.ElapcedMilliseconds);

用另一种方法重复测试。希望能有所帮助。