返回介绍

互斥锁和适当循环的并行处理

发布于 2025-02-18 12:46:47 字数 3575 浏览 0 评论 0 收藏 0

嗯,我猜你和我得出了同样的结论。并行化的 drawTriangle 循环方案似乎并没有成为一个很好的选择。我们需要另外的东西来让线程切换更加高效。我们要并行处理多个三角形,而不是绘制一个三角形。总之,每一个核心都要绘制一个完整的三角形。

这种方法的问题将会在 PutPixel 方法中出现。现在我们要并行处理几个面,我们可能会陷入 2 个内核/线程试图并行访问同一个像素的情况。这是,我们只需要保护要访问的像素就可以了。事实上,如果我们用更多时间去保护正在工作中的数据,并行化将会非常有用。

解决的办法是使用一个锁:

private object[] lockBuffer;

public Device(WriteableBitmap bmp)
{
  this.bmp = bmp;
  renderWidth = bmp.PixelWidth;
  renderHeight = bmp.PixelHeight;

  // 后台缓冲区大小值是要绘制的像素  
  // 屏幕(width*height) * 4 (R,G,B & Alpha 值)  
  backBuffer = new byte[renderWidth * renderHeight * 4];
  depthBuffer = new float[renderWidth * renderHeight];
  lockBuffer = new object[renderWidth * renderHeight];
  for (var i = 0; i < lockBuffer.Length; i++)
  {
    lockBuffer[i] = new object();
  }
}

// 调用此方法把一个像素绘制到指定的 X, Y 坐标上
public void PutPixel(int x, int y, float z, Color4 color)
{
  // 我们的后台缓冲区是一维数组  
  // 这里我们简单计算,将 X 和 Y 对应到此一维数组中  
  var index = (x + y * renderWidth);
  var index4 = index * 4;

  // 使用锁来保护缓冲区不被并行处理扰乱
  lock (lockBuffer[index])
  {
    if (depthBuffer[index] < z)
    {
      return; // 深度测试不通过 
    }

    depthBuffer[index] = z;

    backBuffer[index4] = (byte)(color.Blue * 255);
    backBuffer[index4 + 1] = (byte)(color.Green * 255);
    backBuffer[index4 + 2] = (byte)(color.Red * 255);
    backBuffer[index4 + 3] = (byte)(color.Alpha * 255);
  }
}

使用第二种方法,从 45 FPS 提升到了 53 FPS。你可能会认为这点性能提升并不能让人影响深刻。但是在接下来的教程中,drawTriangle 方法将更加复杂,比如处理阴影和照明之类的,并行处理几乎可以得到两倍的性能提升。

我们还可以看看这个并行处理方法分析的核心利用图:

比较以前的核心图,你就会明白为什么它更加高效了。

你可以在这里下载含有这种优化的 C#版本解决方案:

那么,在 Html5/JavaScript 中为什么不能应用这种方法呢?Html5 在 JavaScript 中卫开发人员提供了一个新的 API 用于处理类似的情况。它叫 Web Workers,使用它可以处理使用多核心的情况。

David Catuhe 和我已经在这三篇话题中讨论过这个东西:

我们使用 message 与 workers 进行沟通。这意味着大多数时间被用于从 UI 线程给 workers 线程传输拷贝数据。我们只有很少部分的类型可以使用。事实上,随着 转换对象 ,当转移到 workers 时原始对象将从呼叫者上下文(UI 线程) 中清除。

但是在我们加速 Html5 的 3D 软件渲染引擎时,这并不是主要的问题。在发送数据的时候将有memcpy()进行操作,这是一个非常快速的过程。但真正的问题是,当 workers 完成了处理后,需要将结果发送回主线程而且这个主线程还需要将数据重新填充回像素数组中。这个操作将很简单的抵消掉所有 Web Workers 带来的性能增益。

所以最后,我还没有找到一个有效的并行处理方法来实现 Html5 中 3D 软件渲染引擎的性能提升。不过,可能我有一些东西还不知道。如果您可以解决当前 Web Workers 的局限,获得到一个显著的性能提升的话,我非常乐意接受建议!

在接下来的教程中,我们将讨论 平面着色和高氏着色 。我们的实现将开始真正耀眼!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文