How do I use multithreading?

Started by
41 comments, last by Trienco 10 years, 6 months ago

Well, I've been looking into multithreading to do a single (but tedious) task. I am creating a space sim that allows the player to travel between stars. During the travel time, I will be generating the "new" star system. This task creates all the planets ,the terrain texture, and the atmosphere textures. Needless to say, this is a HUGE drain on the program; so I broke it up into passes. This works ok, but I still run into systems with a lot of planets, so this takes several thousand passes to get everything generated. This means that some times I reach the system before everything is generated and I had to make a "while" statement to finish the generation.....

I have never done multithreading before and I don't know how to make it work. The examples seem to want me to create the thread and have it exit when finished.


DWORD WINAPI MyThreadFunction( bool Exit ){
	tp3++;

	return 0;
}

(Ignore the "bool Exit" parameter).... This will only increment tp3 once, and that makes sense but when I do something like:


DWORD WINAPI MyThreadFunction( bool Exit ){
	while (true) tp3++;

	return 0;
}

It does nothing at all......

tp3 is a global variable I use in the program. Here is the creation:

HANDLE th=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)&MyThreadFunction,NULL,0,NULL);

I was thinking, perhaps, I should do the thread creation whenever I need to generate and just leave it at that.... Would that work? I don't want to create memory leaks or something like that.....

Advertisement

With while() loop compiler probably put variable into register, so value in memory will never be updated until function is exited or significant part of other code is executed. You can fix this by making variable volatile:


volatile int tp3 = 0;

If you can, refactor it so you're not using the global variable. Especially if it's frequently updated.

Also, look into mutexes and release the lock as soon as you get the data you need from the variable.

Seriously, diving into multithreading without understanding how it affects scope and concurrency is playing with a red giant. Only the red giant is blue because the data you were reading from was changed by another thread mid operation.


Also, look into mutexes and release the lock as soon as you get the data you need from the variable.

I don't know enough to know what that means..... Please explain.

Also, I was wondering if this is ok:


//****** outside the game loop
DWORD WINAPI MyThreadFunction( void ){
	//************* generate solar system here **********
	return 0;
}


//*********** inside the game loop
if (GenSys){
    HANDLE th=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)&MyThreadFunction,NULL,0,NULL);
    GenSys=false;
}

The GenSys is only true on initial "traveling to a new star".

EDIT: I don't think the "shared" data is going to be a problem. The data is only used by other parts of the program (like rendering) once it is fully generated.

No, that's not OK. To understand why, you need to understand things like the C++ memory model (if using C++11) or the platform memory model and ABI and a little bit of processor architecture and OS design (if not using C++11). Also, you need to research data races. All of the things mentioned in your quote that you didn't understand are critical knowledge if you want to do threading yourself and do it right.


Multithreading is seriously difficult and fraught with pitfalls. The best thing you can do is use an existing library like std::thread or Intel's Thread Building Blocks or similar, and not roll your own threading logic.


In other words, this is not something you will learn to a satisfactory extent in a couple of forum posts. If you want to do this yourself, you're in for a lot of studying and experimenting. Otherwise, you should use an existing library instead.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

Ok. I tried to use std::thread, but I don't have c++11.... I'm trying to find a way to get the library.....

Ok. I tried to use std::thread, but I don't have c++11.... I'm trying to find a way to get the library.....

Why don't you have C++11? It is available for all major platforms and compilers.

Recent versions of GCC or Clang require the -std=c++11 option to enable C++11. Visual Studio Express 2012 should support C++11 out of the box.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

I downloaded VS2012, but I can't seem to get my program to compile on it. I am sure I DON'T have it set up right......

EDIT: I must have been doing something stupid. I got it working now...... So, with what I described, does anyone have a SIMPLE example of how to actually do multithreading?

http://en.cppreference.com/w/cpp/thread/thread/join

Simple threading example ... although you may need something a bit more complex for your project.

Cheers!

Threads are not so hard people make them to be. If I understood right about what you want to do this is the easiest multithreading case there is. Correct me if I'm wrong.

You want to have another thread generate your starsystem while your main thread is handling the game. Without the additional thread you would do a small portion of the generation between each frame and the performance is not good enough for you.

There is no data racing or any other complicated stuff going on if you generate the starsystem in a single thread and make sure you do not access the starsystems data from anywhere until the generation is complete. This kind of threading does not take that much effort to get it right and will increase your games performance quite a bit. You only need to have a threadsafe way to tell the main thread if a starsystem is still being generated. You also can use n generation threads to generate n starsystems at the same time.

My tip is to not use any global variables to manage the threading as those get complicated rather quickly. Have a "generated" flag that's defaulted to false and set it true after generation is complete in your starystems class or struct or whatever you use to store your starsystems in memory. You may add a memory barrier to after the starsystem is generated to make sure all threads have the same data.

This way you'll have a full thread generating the starsystem as fast as possible without any need for complicated threadmanagement stuff. A lot of people are trying to scare people away from threads because they don't understand it themselves. Granted there are a lot of complicated stuff to do if you want to multithread realtime simulations but a simple background thread to generate the next part of the gameworld before the player is close enough to interact with the part is a simple task.

You seem to have managed to get a thread going. Just try and put the code to generate a starsystem into the thread and see what happens. If something gets broken and you can't figure out why then come back here and explain what and how and someone will propably be able to help. Multithreading is not rocketsience.

This topic is closed to new replies.

Advertisement