TG2 Parallelism: Questions

Started by Sengin, May 21, 2008, 10:59:00 PM

Previous topic - Next topic

Sengin

To planetside staff:
Is TG2 written in C++?  Since you have it fully parallelized now, I can ask: how do you create the threads used to render on each core?  I ask because there is no standard in C++ to create threads, and the only way I've found is to use Microsofts kernel functions by including windows.h and using the CreateThread() function, and was wondering how you guys (personally) created the separate threads (did you use the CreateThread() function, and if so, how did you do it for the mac version?).  I have recently gotten very interested in parallelism and coding for multi-core machines and was wondering what some developers use to parallelize their applications.  If you used a function created by yourselves you don't have to share it, but can you include some information about it?

Thanks.

jo

Hi,

TG2 is written in C++. We use the cross platform thread support in Boost:

http://www.boost.org

It wouldn have been pretty straightforward to write our own cross platform thread wrapper, but also wrapping all the synchronisation stuff like mutexes might have been a bit trickier and so it made more sense just to use Boost. We use other parts of Boost for various things too.

BTW, apparently on Windows you shouldn't actually call CreateThread(), but rather _beginthreadex(). Makes sense, right?  ??? I have a book called "Programming Applications for Windows" by Jeffrey Richter which talks about this sort of stuff. Nothing much applicable to Windows applications in general, but lots about more advanced stuff like threads and virtual memory. It's pretty old, a newer version is called "Windows via C/C++", I don't have that though. The book I have is an interesting read.

Regards,

Jo



Sengin

Ah, thank you Jo.  I'm glad there's actually progress on creating a standard way to implement threads in C++.  I hadn't heard of boost until now, it sounds very nice.  And thanks for the hint on CreateThread().  I tried looking in _beginthread() earlier, but I couldn't get it to work (probably forgot to include a header file or something), to I tried to get CreateThread() to work.

Thanks!

Sengin

Jo (or anyone else on the coding staff),
Do you know if the mutex operations in Boost use atomic operations?  The reason I'm asking is because of the actual locking of a resource.  If you look at the code

if(!ioLock)
{
    ioLock = true;
    //do some processing
    ioLock = false;
}


If the value of ioLock is false, and then the OS decides to switch threads after the compare but before the setting of the ioLock to true, and another thread runs right through and starts its processing, then undesired (and very bad) results can occur.  After searching around a bit, I found out that a lot of CPUs have atomic instructions like Compare-and-Swap, but nothing would say how to cause a C++ compiler to use those instructions.  And I couldn't find out if the mutex operations in Boost actually use these operations to prevent another thread to begin executing in the middle of certain instructions.

Thanks.

Matt

#4
I'm not sure where that code comes from, but in short the answer is yes. The whole purpose of Boost Mutex is to be a resource that can only be acquired atomically (or the lock on it, anyway). The OS provides functions to enter critical sections, acquire atomic access to resources etc., and the classes in Boost Threads are designed to use those and take care of all that low level stuff for you, no matter what OS you're running on.

Matt
Just because milk is white doesn't mean that clouds are made of milk.

Sengin

I was just using the code as a simplified example.  I was pretty sure that the Boost mutex acquired locks atomically, but wasn't definite (until now).  Thanks Matt!

jo

Hi Sengin,

I have never had to explicitly use atomic operations ( these being atomic operations like you were talking about, not mutexes etc. ) but Windows and the Mac OS have functions for them, so you don't have to call the processor instructions via assembler. Here's the Mac ones :

http://developer.apple.com/documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/chapter_5_section_6.html

Windows has the Interlocked family of functions :

http://msdn.microsoft.com/en-us/library/ms686360(VS.85).aspx

The only reason I looked these up was that I was interested to see them as well :-). As you'll see these functions are all in same parts of the documentation as other threading stuff.

Regards,

Jo

Sengin

Quote from: jo on May 29, 2008, 09:41:51 PMThe only reason I looked these up was that I was interested to see them as well :-). As you'll see these functions are all in same parts of the documentation as other threading stuff.

Yeah, I was thinking about potential errors with threading while trying to fall asleep (yeah, I know, that's not really something to be thinking about when trying to fall asleep :P), and the problem of the OS switching after the check for the lock and before acquiring the lock drifted through my head...needless to say, it took a while to fall asleep because I couldn't come up with a solution (isn't it crappy when you find a problem but don't have a clue how to solve it because it's outside of your experience?).  The following morning I looked it up and found the solution was through atomic instructions, but couldn't find a way to implement them.  So I came to you guys, whom I know had to deal with this problem, either directly (using the OS' atomic synchronization functions) or indirectly (included with the locking of a mutex in boost).

Thanks for your help!