Null pointer error in thread

Does P2D natively have access to all cores, as yes that was my problem. I shall add a sleep function to the functions, is there any standard time period which is recommended?

Aye it is rather puzzling right now, but we have some knowledgeable individuals here providing input, so if I sit down long enough and read their comments I should figure it out eventually.

I repeat, all the renderers are single threaded :wink: so, no, but some are more efficient than others. And of course, OpenGL will do a lot more of the work on the GPU not CPU.

Don’t add a sleep in the animation thread! Only if you’re doing something on another thread.

this is the part of the program I want to multithread

int W = 1200,H = 600,threads = 2;
Grid g;
void settings(){
   size(W,H);
};

void setup(){
  g = new Grid(W,H,10);
  //thread(new g).start;
};

void draw(){
  background(0);
  
  g.spawn();
  fill(255);
  text(frameRate,100,200);
};

class Grid{
  
  float w,h,scale,seed = 10,x,y,freq = 1,amp = 1;
  
  int res,cols,rows;
  float [][] map;
  
  Grid(float W,float H,int Res){
    
    cols = int(W/Res);
    rows = int(H/Res);
    res = Res;
    map = new float[cols][rows];
    scale = 0.05;
    seed = 10;
    noiseSeed(int(seed));
    
  };
  
  Grid(float X,float Y,float W,float H,int Res){
    
    x = X;
    y = Y;
    cols = int(W/Res);
    rows = int(H/Res);
    res = Res;
    scale = random(10);
    map = new float[cols][rows];
    scale = 0.05;
    
  };
  
  
  void spawn(){
    //x = mouseX-W/2;
    //y = mouseY-H/2;
    amp = map(mouseY,0,height,1,2);
    freq = map(mouseX,0,width,1,2);
    if(scale<=0)scale = 0.0001;
    
      for(int i=0;i<rows;i++){
        for(int j=0;j<cols;j++){
          
          float yy = scale*i*freq;
          float xx = scale*j*freq;
          
          noStroke();
          float height = map(noise(xx,yy)*amp,0,1,0,255);
          
          color col = 0;
          if(height>50)col = color(0, 0, 153);
          if(height>100)col = color(204, 204, 0);
          if(height>150)col = color(51, 153, 51);
          if(height>200)col = color(102, 102, 153);
          
          fill(col);
          rect(j*res,i*res,res,res);
        
      }}
  //fill(255);
  //text(amp,100,210);
      
  };
  
};

I was hoping to be able to split the for loop into the number of threads I wanted to use.

No I have used everything from 20 to 100ms in the past. It depends a little on the framerate and how long the while-loop code takes to execute. I suggest about 50ms so the main thread has plenty of time to what it must.

There is nothing in there that you can feasibly or reliably multithread *. Try using size(W, H, P2D); and see if that’s any better.

* OK, theoretically you might be able to map all the heights across cores before rendering, but that should not be a bottleneck and there’s a very good chance it would end up slower while being more complicated - concurrency adds its own overheads.

asI recall this is why I originally opted for FX2D as P2D didn’t offer better performance, gpu utilization is nearly 0, and cpu is stuck at 34, whilst framerate is at 19, however I may be doing something wrong

would you recommend using this example you posted a while back, I held of on implementation as I didnt understand everything, and was also focusing on gui.

/**
 * Linked Balls (v4.31)
 * (Double Buffer Remix)
 *
 * by  NatashaGunaratna (2014/Feb)
 * mod Quark & GoToLoop
 *
 * Forum.Processing.org/two/discussion/5886/multithreading-madness#Item_17
 *
 * Forum.Processing.org/two/discussion/3087/
 * how-to-draw-lines-between-my-circles-where-they-overlap#Item_3
 *
 * Studio.ProcessingTogether.com/sp/pad/export/ro.989GaZC5t7EkE
 */
 
static final int FPS = 60, DELAY = 1000/FPS >> 2;
static final int NUM = 0100, MIN = 020, MAX = 0100;
final Particle[] balls = new Particle[NUM];
 
static final String ENGINE = JAVA2D;
//static final String ENGINE = FX2D;
//static final String ENGINE = P2D;
//static final String ENGINE = P3D;
 
PGraphics mainCanvas, altCanvas;
boolean isMainCanvas, isLooping = true;
 
void setup() {
  size(800, 600, ENGINE);
  frameRate(FPS);
 
  for ( int i = 0; i != NUM; balls[i++] = new Particle(
    random(MAX>>1, width - MAX), random(MAX>>1, height>>1), 
    (int) random(MIN, MAX)) );
 
  mainCanvas = createCanvas();
  altCanvas  = createCanvas();
 
  thread("render");
}
 
void draw() {
  background(isMainCanvas? altCanvas : mainCanvas);
  frame.setTitle("FPS: " + round(frameRate));
  //surface.setTitle("FPS: " + round(frameRate));
}
 
void mousePressed() {
  if (isLooping ^= true)  loop();
  else                    noLoop();
}
 
void keyPressed() {
  mousePressed();
}
 
void render() {
  final PGraphics main = mainCanvas, alt = altCanvas;
  final Particle[] particles = balls;
 
  while (true) {
    final PGraphics pg = isMainCanvas? main : alt;
    final int fc = frameCount;
 
    pg.beginDraw();
    pg.background(-1);
 
    for (int j, i = 0; i < NUM; ) {
      pg.stroke(0);
      final Particle b = particles[j = i++].script(pg);
 
      pg.stroke(Particle.LINK);
      while (++j < NUM) {
        final Particle p = particles[j];
        if (b.isIntersecting(p))  b.linkToParticle(p, pg);
      }
    }
 
    pg.endDraw();
    isMainCanvas ^= true;
 
    if (fc == frameCount) {
      println();
 
      do {
        print(".");
        delay(DELAY);
      } while (fc == frameCount);
    }
  }
}
 
PGraphics createCanvas() {
  final PGraphics pg = createGraphics(width, height,FX2D);
 
  pg.beginDraw();
  pg.colorMode(RGB);
  pg.ellipseMode(CENTER);
  pg.smooth();
  pg.noFill();
  pg.strokeWeight(2);
  pg.endDraw();
 
  return pg;
}
 
final class Particle {
  static final color LINK = #FF4040;
  static final float GRAV = .15;
 
  float x, y;
  final short d, r;
  float sx = random(.3, 1.5), sy = random(.1, .5);
 
  Particle(final float xx, final float yy, final int dd) {
    x = xx;
    y = yy;
    d = (short) dd;
    r = (short) (dd>>1);
  }
 
  Particle script(final PGraphics pg) {
    return move().bounce().gravity().display(pg);
  }
 
  Particle move() {
    x += sx;
    y += sy;
 
    return this;
  }
 
  Particle bounce() {
    if (x > width  - r | x < r) {
      sx *= -1.;
      move();
    }
 
    if (y > height - r | y < r) {
      sy *= -1.;
      move();
    }
 
    return this;
  }
 
  Particle gravity() {
    sy += GRAV;
    return this;
  }
 
  Particle display(final PGraphics pg) {
    pg.ellipse(x, y, d, d);
    return this;
  }
 
  Particle linkToParticle(final Particle p, final PGraphics pg) {
    pg.line(x, y, p.x, p.y);
    return this;
  }
 
  boolean isIntersecting(final Particle p) {
    return sq(p.x - x) + sq(p.y - y) < sq(p.r + r);
  }
}

using the register method, i’m still struggling with implementation, i’m following your example.

String [] messages = {"Test string for secondary thread",
                      "Here's another message.",
                      "And this is yet another thread."};
                      
int [] numbers = { 0,1,2,3,4,5,6,7,8,9,10};
int threads = 1;
                      
void setup(){
  size(200,200);
  
  for(int i=0;i<threads;i++){
    
    new Thread(new A(numbers)).start();
  }
};

void draw(){
  background(0);
  fill(255);
  text(frameRate,100,100);
};

class A implements Runnable {
  String to_print;
  int t,count = 0;;
  boolean ints,intss,strings;
  int [] numbers = new int[1];
  String [] messages = new String[1];
  
  A(String to_print) {
    this.to_print = to_print;
  };
  
  A(Integer t) {
    this.t = t;
    intss = true;
  };
  
  A(String [] messages) {
    this.messages = messages;
    strings = true;
  };
  
  A(int [] numbers) {
    this.numbers = numbers;
    ints = true;
  };
  
  public void run() {
    registerMethod("draw", this);
    draw();
  };
  
  public void draw(){
    unregisterMethod("draw", this);
  
    try {
      display();
    }
  
    catch (final AssertionError err) {
      System.err.println(err);
    }
  };
  
  void display(){
    while(true){
      count++;
    //if(ints)System.out.println(count);
    //displayMessages();
    displayNumbers();
  }
  };
  
  void displayMessages(){
    if(strings)
    for(int i=0;i<messages.length;i++){
      
    String message = messages[i];
    
    fill(255);
    text(message,100,100);
    }
  };
  
  void displayNumbers(){
    if(ints){
    //text(count,100,100);
    fill(255);
    rect(10,10,width-20,height-20);
    //System.out.println(count);
    //for(int i=0;i<numbers.length;i++){
      
    //int number = numbers[i];
    
    //fill(255);
    //text(numbers.length,100,100);
    //}
    }
  };
};

Out of these two does the PApplet offer a significant performance increase? I’m comfortable handling PGraphics, not so much on the PApplet.

That was sorta PGraphics double-buffer threading example.

Its main idea is to display 1 PGraphics on the “Animation” Thread, while the “render” Thread is busy rendering the other PGraphics.

Maybe, not sure. But w/ a separate invisible PApplet you can use the FX2D engine, while on a separate PGraphics it can’t be FX2D.

You’re not supposed to unregisterMethod() it! It’s a fixed callback.

Also it’s from there you need to call your other drawing methods, so they happen under the “Animation” Thread.

Aye!! still get a null pointer

public void run() {
    registerMethod("draw", this);
    draw();
  };
  
   void draw(){
    //unregisterMethod("draw", this);
  
    try {
      display();
    }
  
    catch (final AssertionError err) {
      System.err.println(err);
    }
  };
  
  void display(){
    while(true){
      count++;
    //if(ints)System.out.println(count);
    //displayMessages();
    displayNumbers();
  }
  };

I can replicate that. Similar here, except CPU 100% (top on Linux doesn’t normalise). The bottleneck is in the renderer - tried removing everything that is feasibly multi-threadable and performance is about the same.

I think you need to look at using a PShape to contain your grid geometry so it’s only calculated once. There’s a 3D one in Examples / Demos / Performance / CubicGridRetained. Altering pre-made shapes can be slow, but looping through and changing the fill colour seems to work. Scaling may need a rethink, but you should be able to get the same effect scaling the whole rendering?

1 Like

Why are you directly invoking draw() there?
We shouldn’t invoke callbacks by ourselves.
That’s why you are registering it, so it’s invoked by something else.

That try / catch block is outta place there! There’s nothing to be caught!

Inside that custom draw() callback you need to place all the stuff that can’t be done outside the “Animation” Thread.

do you have a link to more in depth documentation for registerMethod?

Nope! I’ve learned what I have by reading PApplet’s source code: :nerd_face:

:pensive:Yikes, my old enemy, reading source code.

its just removing the draw method the canvas now display nothing, but no error…

void run() {
    registerMethod("draw", applet);
  };
  
   void draw(){
      display();
  };

Oh, I’ve forgotten a very important “ingredient” so registerMethod() can actually work.

Your class gotta have public access level:
class A implements Runnable { -> public class A implements Runnable {

1 Like

If you’re looking to do multi-threaded drawing, this may be of use to you:

3 Likes

so some partial success,
this throws out no errors however nothing else happens, console isn’t logged and text is no longer displayed even in the main draw loop. I’m clearly missing some prerequisites hear in term of how this function call works. I’ll have to take a look at the source code to get a more in depth look.