Multithreading Advice

Hello,
I am trying to optimize a little LOD program and was looking into multithreading. I am not sure what tasks should be separate threads though… In the update loop I create update the vertex buffers like so:
[java]
VertexBuffer vb = mesh.getBuffer(Type.Position);
VertexBuffer ib = mesh.getBuffer(Type.Index);
vb.updateData(BufferUtils.createFloatBuffer(vertices));
ib.updateData(BufferUtils.createIntBuffer(indices));
[/java]
This takes a fair amount of time and I thought that passing it off to a thread would help. The thing is the vertices and indices are created at the “end” so there is really no more work to be done after the buffers are updated. I also have a task in which I scroll through a list of quads (using a for loop) and gather their vertices. Would this be a good thing to push into a callable?
Thanks for any helpful words.

No code runs faster just because it is in a thread. You generally create threads if you are waiting for something and can do other work instead of waiting. Example, the render loop could render a ‘loading’ screen while waiting, the network server can write to disk while waiting for new packets to arrive and so on.
So to answer the question “should I do this in the background” you should have an idea on what the application can meaningfully do while waiting for the thread to complete.

Well, that’s not quite true. Modern hardware has multiple cores so you can offload intensive calculations (for example AI pathfinding) to other cores by spinning off a thread for them and keep the render thread running well on its own core.

Yes that’s true. In the OP case it would mean changing buffers in the background and using them when they are done. Taking care to synchronize the writing to the buffers with the render loop reading. Maybe switching buffers or some other scheme to keep the threads from stepping on each other. It might be worth a try, as with all optimizations you should measure before and after to see what the impact is.

ACtually if you dont cahnge the size of buffers they are suprisingly threadsave, why? Jme uploads changed buffers, but only if it knows they are changed, so if you can ensure that it is not accessing them while you change them it’s save to manipulate them from another thread.

Hmm, that’s slightly risky though, Might come back to bite you in the future.

(For example lets say the object is removed from the scene then re-added later. It will then have the buffers sent at the point of re-adding and the buffers may be mid-modification at that time). That then leads to weird occasional and random visual artifacts which are a pain to track down.

Yes, it is risky and definitly adv. only. (I use this for updating of a terrain in the background without problems tho, but you realy must ensure that it is accessed in a controlled and safe way only.

<cite>@jmaasing said:</cite> Yes that's true. In the OP case it would mean changing buffers in the background and using them when they are done. Taking care to synchronize the writing to the buffers with the render loop reading. Maybe switching buffers or some other scheme to keep the threads from stepping on each other. It might be worth a try, as with all optimizations you should measure before and after to see what the impact is.
I tried this but I don't think there was much of a performance boost. I may try to tweak it a bit to try to make it better but at this point I am doubtful.

I was also wondering if there was any way to spread a process over multiple frames?

Um… are you generating the LOD’s on the fly? or are the LOD’s predefined?

If you can avoid the BufferUtils.createXBuffer calls, things are going to go a lot smoother all the way around.

The way it looks from the code posted, you’re allocating direct memory buffers every time the LOD switches. So, if you were to run forward, run backward, run forward, run backward, over and over again… you’re recreating the buffer for the same 2 LOD’s. This = bad.

Or am I missing something?

EDIT: Other options…

  1. Allocate the maximum size buffer you’ll need and then only use reuse what you need (thus the capacity/limit)
  2. Preallocate the FloatBuffer(s)/ShortBuffer you’ll need for each LOD, then just swap them out.

I’m sure there are more.

<cite>@t0neg0d said:</cite> Um... are you generating the LOD's on the fly? or are the LOD's predefined?

If you can avoid the BufferUtils.createXBuffer calls, things are going to go a lot smoother all the way around.

The way it looks from the code posted, you’re allocating direct memory buffers every time the LOD switches. So, if you were to run forward, run backward, run forward, run backward, over and over again… you’re recreating the buffer for the same 2 LOD’s. This = bad.

Or am I missing something?

EDIT: Other options…

  1. Allocate the maximum size buffer you’ll need and then only use reuse what you need (thus the capacity/limit)
  2. Preallocate the FloatBuffer(s)/ShortBuffer you’ll need for each LOD, then just swap them out.

I’m sure there are more.

This is done on the fly. The LOD is for a very large area so I think preallocating the memory for the buffers would cause issues. The way I do it is to simply delete the data for leaf-nodes once they are out of view.