How to improve performance: multiple array operations on pixels

Hi all :slight_smile:
I’m back to processing. I was using this tool when i was student 10 years ago, and its really pleasure to re-use it !

I’m triyng to use Kinect to generate design and im working to calculate pixels data evolutions, that mean i need to use long multiple array treatment… This work make slowdown my screenview… Anyone know a Library or a tips to improve performance ?
Thank you !! :slight_smile:

Hi @flodeux,

Welcome back! :wink:

Most of the time it’s done using Multithreading which works by breaking your problem into smaller ones and solving them in parallel in different threads.

I don’t know the internals of how your algorithm works but you can also find ways to improve efficiency with programming / algorithmic tricks. (choosing the right data structures, avoid cache misses and useless memory allocations…)

1 Like

Hi, thank you for the answer.
That mean i need to try using the “thread()” class ? (thread() / Reference / Processing.org)
I will try that, im using

  for (int y=0; y<elmt.height; y++){
    for (int x =0; x<elmt.width; x++){..}}

I’ll may try something like

for (int y=0; y<elmt.height; y++){thread("threadX");}

I hope i can have a way to pass argument to the thread call.
It is something like that, you was thinking about ?

Thank you very much :wink:

.Flodeux.

Hi @flodeux,

Sorry for the late answer :wink:

The Processing thread() function is a wrapper for easily creating a Thread instance that launches a method defined earlier. (see the actual code here).

What you need to do is to break your image into square tiles, one for each thread, do the computation of each specific tile and then wait for all the threads to finish.

This is an example by extending the Thread class and assigning a random color for each time:

class TileThread extends Thread {
  int x, y, w, h;
  color randomColor;

  TileThread(int x, int y, int w, int h) {
    this.x = x;
    this.y = y;
    this.w = w;
    this.h = h;

    randomColor = color(random(255), random(255), random(255));
  }

  void run() {
    for (int i = x; i < x + w; i++) {
      for (int j = y; j < y + h; j++) {
        int loc = i + width * j;
        pixels[loc] = randomColor;
      }
    }
  }
}

int nTiles = 5;

void setup() {
  size(500, 500);
}

void draw() {
  int tileSizeX = width / nTiles;
  int tileSizeY = height / nTiles;
  ArrayList<Thread> tileThreads = new ArrayList();
  
  loadPixels();
  
  // Create one thread for each square tile (like a grid)
  for (int i = 0; i < nTiles; i++) {
    int x = i * tileSizeX;
    for (int j = 0; j < nTiles; j++) {
      int y = j * tileSizeY;
      
      Thread thread = new TileThread(x, y, tileSizeX, tileSizeY);
      thread.run();
      tileThreads.add(thread);
    }
  }
  
  // Wait for all the threads to finish
  for (Thread thread : tileThreads) {
    try {
      thread.join();
    } catch (InterruptedException e) {
      println(e);
    }
  }

  updatePixels();
}

(this works when the canvas size is divisible by nTiles but you can support non square tiles)
(be careful not to modify the same tiles from two different threads leading to a race condition)

2 Likes

Hi Josehh! Thank you for your answer :slight_smile:
Yes i was trying with Thread, but it was impossible to send var to the Thread, maybe this way would be better for me, I’ll try and decompose this to understand, thank you very munch !! :slight_smile:

1 Like

Hi @flodeux,

if you still want more performance and ready for new experiences considering the usage of shaders
… as a future step … :slight_smile:

Cheers
— mnse

processing java version
PShader myshader;

void setup() {
  size(400, 400, P2D);
  myshader=new PShader(g.parent, vertexShader, fragmentShader);
}

void draw() {
  int tileSizeX = width/8;
  int tileSizeY = height/8;

  for (int y=0; y<=height; y+=tileSizeY) {
    for (int x=0; x<=width; x+=tileSizeX) {
      myshader.set("color", random(1), random(1), random(1));
      shader(myshader);
      rect(x, y, tileSizeX, tileSizeY);
    }
  }
}

String[] vertexShader = {"""
#version 330 core
precision highp float;
uniform mat4 transformMatrix;
layout (location = 0) in vec4 position;

void main()
{
  gl_Position = transformMatrix * position;
}
"""};


String[] fragmentShader = {"""
#version 330 core
precision highp float;
uniform vec3 color;
out vec4 glFragColor;

void main()
{
  glFragColor = vec4(color, 1.0);
}
"""};
converted to p5 to visualize:

PS:

p5 code:
let myshader;

function setup() {
  createCanvas(400, 400, WEBGL);
  noStroke();
  myshader = createShader(vertexShader, fragmentShader);
}

function draw() {    
  translate(-width/2,-height/2);
  var tileSizeX = width / 8.;
  var tileSizeY = height / 8.;
  for (var y = 0; y <= height; y += tileSizeY) {
    for (var x = 0; x <= width; x += tileSizeX) {
      myshader.setUniform("color", [
        Math.random(),
        Math.random(),
        Math.random(),
      ]);
      shader(myshader);
      rect(x, y, tileSizeX, tileSizeY);
    }
  }
}

const vertexShader = `
precision highp float;
uniform mat4 uProjectionMatrix;
uniform mat4 uModelViewMatrix;
uniform mat4 uModelMatrix;

attribute vec3 aPosition;

void main() {
  vec4 positionVec4 = vec4(aPosition, 1.0);
  positionVec4.xy = positionVec4.xy * 2.0 - 1.0;
  gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;  
}
`;

const fragmentShader = `
precision highp float;
uniform vec3 color;

void main()
{
  gl_FragColor = vec4(color, 1.0);
}
`;
1 Like