c# - 读取字节数组与 int 数组和位移位 - 哪个更快?

标签 c# optimization

其中一个明显更快吗?

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);
}

最佳答案

在 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;
}

另请注意,如果您从位图图像读取数据,它不会存储为连续的像素数据数组。扫描线之间可能存在填充,因此代码只能从单个扫描线读取像素,无法安全地从整个图像读取数据。

编辑:

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

关于c# - 读取字节数组与 int 数组和位移位 - 哪个更快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6856649/

相关文章:

c# - 如何使用 Entity Framework 保存外键?

c# - 在事件处理程序中保留 'new' 是否会导致垃圾过多?

c - C 编译器如何始终如一地优化无法访问的代码?

c# - .NET 6 - 带有 CamelCase 的 AddJsonOptions 不起作用

c# - 由于 EditorConfig,Visual Studio 不会在 'internalclass' 之间放置空格

c# - CMS 的架构

python - while循环,永远运行或倒计时

c++ - 有没有一种访问函数外信息的好方法?

c - 在以下 C 代码中应优化哪个变量

java - 最小化 Spring Boot 启动时间