处理2 - 线程是否会加速渲染许多对象?

时间:2015-04-21 19:49:23

标签: java multithreading optimization processing

我正在处理草图:https://github.com/davidcool/processing/tree/master/polyhedrons/polyhedrons_4

代码不是很优雅,但工作正常。它将旋转的复杂(意味着多个面)多面体渲染到屏幕上。每次单击它时都会添加5个新的旋转多面体对象...一旦你有20-25个物体,它就会开始陷入困境,这意味着帧数/秒会下降,看起来很跳跃。

我一直在阅读Processing / Java中的线程。所以我开始想,也许我可以将对象的总数分成每个处理核心。我特别看到了这个例子:http://www.camnewnham.com/threading-in-processing/

在我深入了解这个鹅追逐之前,有没有人知道线程在动画速度方面是否会有所帮助?当我通常运行草图时,它总是只使用一个核心用于绘制循环?线程可以分散对象动画渲染超过"空闲"芯

谢谢!

1 个答案:

答案 0 :(得分:2)

draw()函数总是由同一个Thread调用。同样的Thread也调用了mousePressed()和类似的函数。在Processing中,这称为动画线程 - Java有类似的想法,称为EDT。

所以你不能简单地将你的绘图移动到其他线程。这将导致渲染问题 - 例如,动画线程可能正在尝试绘制下一帧,而绘制线程仍在尝试绘制前一帧。它不会起作用。

可以尝试通过让所有帮助程序线程绘制到PGraphics而不是直接调用Processing绘图方法来进行自己的多线程屏幕外缓冲。然后,您必须同步所有绘图线程,并且只有在所有这些线程完成后才将您的PGraphics绘制到屏幕上(使用动画线程)。

这不是一项特别困难的工作,但它确实涉及对线程如何工作的相当不错的理解,这超出了大多数处理草图的范围。

另请注意,JavaScript没有多个线程,因此使用线程进行的任何操作都无法在JavaScript模式下运行。

这是一个示例草图,它仅使用动画线程每帧绘制10000个随机点。我用它得到大约7 FPS:

PGraphics sharedGraphics;

void setup(){
  size(500, 500);
  sharedGraphics = createGraphics(500, 500);
}

void draw(){

 sharedGraphics.beginDraw();
 sharedGraphics.background(0);
 for(int i = 0; i < 10000; i++){
   sharedGraphics.ellipse(random(500), random(500), 5, 5);
 }
 sharedGraphics.endDraw();

 image(sharedGraphics, 0, 0);
 println(frameRate);
}

以下是如何使用多个线程渲染到PGraphics:

PGraphics sharedGraphics;

void setup() {
  size(500, 500);
  sharedGraphics = createGraphics(500, 500);
}

void draw() {

  ArrayList<Thread> threads = new ArrayList<Thread>();

  sharedGraphics.beginDraw();
  sharedGraphics.background(0);
  for (int i = 0; i < 100; i++) {
    Thread t = new DrawThread();
    threads.add(t);
    t.start();
  }

  for (Thread t : threads) {
    try {
      t.join();
    }
    catch(InterruptedException e) {
      e.printStackTrace();
    }
  }

  sharedGraphics.endDraw();

  image(sharedGraphics, 0, 0);
  println(frameRate);
}

class DrawThread extends Thread {
  public void run() {
    for (int i = 0; i < 100; i++) {
      sharedGraphics.ellipse(random(500), random(500), 5, 5);
    }
  }
}

然而,它的性能甚至比单线程模型更差,我得到奇怪的工件(一些椭圆被填充,其他则没有),这表明PGraphics不是线程安全的。这可能取决于您正在使用的渲染器类型。然后,您可以添加一些同步:

class DrawThread extends Thread {
  public void run() {
    for (int i = 0; i < 100; i++) {
      synchronized(sharedGraphics) {
        sharedGraphics.ellipse(random(500), random(500), 5, 5);
      }
    }
  }
}

这样可行,但它的性能更差,因为你仍然只能一次访问一个线程的PGraphics,并且每次调用draw()时你都会做一些额外的工作。 / p>

你可能可以摆弄它以使其发挥作用,但最终的结果是它可能不值得。

  

“有些人在遇到问题时会想”我知道,我会使用多线程“。不管怎样,我都会讨厌。”