Concurency in 3d engine.

The thing about multithreading is that it doesn’t need to be hard. The big issues are up front design centered around isolation of tasks, minimal to no sharing of “state” data and not writing concurrency based data-structures and algorithms (let someone else do that for you). Ideally thread communication should be single producer & single consumer…oh and have I mentioned avoid lock-like structures like the plague. I actually find single-threaded design much harder because you (typically if you have moderate to higher complexity) have to worry about worst case timings of everything to prevent things from getting foo-bared (well unless you have a soft/hard realtime dedicated OS that allows writing of interrupt handlers).

As an example. There’s no specific reason to insist that at some timestamp X that a rendering thread and a simulation thread must “see” the world state as being the same. Doing so make everything much so harder for no useful reason. The rendering thread simply needs to have a plausible and internally consistent world view to show the given player at the current frame. Design by composition and data segregation are very handy skills to develop.

Sadly so much of literature, teaching, etc. is based around architectures which haven’t been around for decades and given the raw numbers of people learning CS the tendency to give “every problem is a nail” scenarios. Personally I’d let to see a lot more of “write high level, think low level” and acknowledging that CS is applied mathematics and the only want to learn is to get off your ass and work problems (as opposed to which solution fits the problem).

@lukasz1985
I don’t agree with most of what you’re saying.

Like you said, “big” problems can always be divided into a number of smaller problems, with part of the problem being how these parts should interact. Minimizing the areas where the problems overlap is the most important thing to do, since a small problem without complex interactions with other problems is a simple problem. Never try to solve a big problem, always divide and conquer.

Locks are not useful for programming. Locks are a way of turning a parallel program into a serial program. For games, the focus is either on increasing performance through parallel computing, or on responsiveness (allowing the UI to continuously update while doing heavy computations in another thread). Therefore locks should be avoided as much as possible. There are almost always lock-less solutions to a problem. Have 4 threads writing to a shared list? Just give each thread its own list. If you for some reason need a single list, then just merge them all into one list when you’re done, preferably while something else is being done on other threads. Bam, no more locking overhead keeping 4 threads busy 75% of the time. From my experience the only time I’ve not been able to get rid of my locks/synchronization is when coordinating which threads should do what. After that’s sorted out you shouldn’t need any synchronization of any kind.

I don’t think most people here think that programming is especially painful. I’m sure some people like the “IT’S FINALLY DONE”-part more than mindless bean making, but the part I enjoy the most is coming up with a fancy algorithm for doing something and then implementing it. It’s the challenge for me.

Avoiding libraries can be a good way to learn new things. For example, using OpenGL directly instead of using an engine built on top of OpenGL will usually be faster since you can do some pretty cool low-level optimizations that can be hard to pull off without a specifically tailored solution to the specific problem. But the same can be said about OpenGL itself. Why use OpenGL when you can interact directly with the GPU? You must know that this is a Java forum, so by simply being here you’re using the Java garbage collectors and built-in libraries. Everyone draws the line somewhere. I think Java has lots of convenient features like garbage collection that lets me focus on what I find interesting instead of bothering with manually freeing pointers. The cost is a garbage collection pause every now and then, but through smart coding that can be kept to a minimum. Plus, I bet that the Java garbage collectors are better at their job than any memory manager I could possibly manage to write myself in C or C++ for example, but I digress. The point is that everyone draws their line somewhere depending on how close to the hardware they want to be. Every level of abstraction costs performance and flexibility, but reduces the time it takes to code and the complexity of the code.

On another hand, I think it’s important to have a deeper understanding about the underlying libraries to be able to code effectively. If you don’t know what the library/hardware you use is doing, you won’t be able to optimize your code well. I guess this is more true for OpenGL than Java, but it can be applied to both. Unless you know how CPU caches work, you won’t understand why LinkedList is so much slower than ArrayList. Unless you know how z-buffering works, you won’t understand why transparency is so hard in 3D. If you don’t know assembler, you won’t know why [icode]i++;[/icode] is not thread safe. I don’t have to code my own Java VM or OpenGL driver to understand how to properly use Java and OpenGL, but I do need to know how they work to some extent.

Your last statement confused me a bit. Why would proper multithreading introduce a delay? The whole point should be to improve performance and/or responsiveness, and both of those should imply a reduced input delay. You’re completely missed the point of multithreading in that case.

On locks: SEE the search keywords I listed above…or look at the docs of most of the concurrency package…and those are designed to be general purpose. Complex data structures can be formed without ever needed say a mutex (or worse a critical section) which can be concurrently accessed by an arbitrary number of threads. You don’t need locks. On learning…I’m sticking to don’t write concurrent algorithms or data structures (at least ones you actually intend to use). Java’s a little easier because you don’t have to worry about the ABA problem…but you need mathematically “prove” your implementation is correct (Unit tests? Ha!) for anything beyond dead easy. Don’t bother. Let people that spend their lives on the topic do the heavy lifting for you.

I almost wept with joy when consumer hardware became advanced enough to use CAS & LL/SC (sigh).