Jump to content

C++ threading performance

Go to solution Solved by mathijs727,
18 hours ago, Tornation said:

 

Thank you guys, will check it out. Sorry for late reply.

Starting/killing threads is very expensive, doing it 60 times a seconds is not efficient.

That way of threading only works when you have a ton to do in those threads so that the overhead of starting/killing threads is low compared to the total execution time of the program.

 

All modern game engines use some kind of task system (often using a task graph).

 

For a simple engines like yours you could consider:

 - start threads at start up

 - have a thread safe queue from which all worker threads get work when they're not doing anything

 - put tasks in the queue from the main thread

 

This is called the producer/consumer pattern.

Tasks would be structs containing a data pointer and a function pointer (which will get executed on the data).

Make sure that everything is thread safe and there are no race conditions.

More advanced systems let tasks spawn new tasks creating a graph.

One of the hardest parts is to make sure that graph gets executed as efficiently as possible.

 

There are a couple of good talks available from GDC vault for free:

http://www.gdcvault.com/play/1012321/Task-based-Multithreading-How-to (maybe a bit too old/outdated (2010), havent seen it myself)

http://www.gdcvault.com/play/1022106/Lessons-from-the-Core-Engine (destiny's multithreaded engine)

http://www.gdcvault.com/play/1021926/Destiny-s-Multithreaded-Rendering (more about destiny's multithreaded engine)

http://www.gdcvault.com/play/1022186/Parallelizing-the-Naughty-Dog-Engine (parallelizing the last of us engine for the PS4 remastered version, really good talk IMO)

 

Furthermore, I found this blog to be quite informative:

https://blog.molecular-matters.com

Short:

If you are large amounts of threads per second (>60), is there so much overhead that it is not really worth it.

 

long:

I am trying my hand at making a rudimentary game engine as an experiment (I'm kind of a noob). My program has a main thread which handles all rendering. Right before that threads starts to render a frame it starts a new thread to process game events. When rendering is done it waits for the game thread to finish then the cycle restarts. My question is since the game thread keeps finishing and then being re created again and again is performance going to hurting significantly? CPU usage is relatively high when running the program. 

 

P.S.

If what I'm doing is OK, is there any way to get rid of the spam of "The thread # has exited with code 0 (0x0)" spam in the visual studio console.

~ Luc Luc

Link to comment
https://linustechtips.com/topic/606000-c-threading-performance/
Share on other sites

Link to post
Share on other sites

5 minutes ago, Tornation said:

If what I'm doing is OK, is there any way to get rid of the spam of "The thread # has exited with code 0 (0x0)" spam in the visual studio console.

I don't think you can remove that.

6 minutes ago, Tornation said:

I am trying my hand at making a rudimentary game engine as an experiment (I'm kind of a noob). My program has a main thread which handles all rendering. Right before that threads starts to render a frame it starts a new thread to process game events. When rendering is done it waits for the game thread to finish then the cycle restarts. My question is since the game thread keeps finishing and then being re created again and again is performance going to hurting significantly? CPU usage is relatively high when running the program

You might want to make game thread non-restarting, the script restarts itself in code, not launching a new one.

Link to comment
https://linustechtips.com/topic/606000-c-threading-performance/#findComment-7850022
Share on other sites

Link to post
Share on other sites

5 minutes ago, NojusTechTips said:

I don't think you can remove that.

You might want to make game thread non-restarting, the script restarts itself in code, not launching a new one.

I'm afraid I don't really follow how that can be accomplished.

~ Luc Luc

Link to comment
https://linustechtips.com/topic/606000-c-threading-performance/#findComment-7850035
Share on other sites

Link to post
Share on other sites

33 minutes ago, Tornation said:

Short:

If you are large amounts of threads per second (>60), is there so much overhead that it is not really worth it.

 

long:

I am trying my hand at making a rudimentary game engine as an experiment (I'm kind of a noob). My program has a main thread which handles all rendering. Right before that threads starts to render a frame it starts a new thread to process game events. When rendering is done it waits for the game thread to finish then the cycle restarts. My question is since the game thread keeps finishing and then being re created again and again is performance going to hurting significantly? CPU usage is relatively high when running the program. 

 

P.S.

If what I'm doing is OK, is there any way to get rid of the spam of "The thread # has exited with code 0 (0x0)" spam in the visual studio console.

All of my C/C++ experience is on *nix systems so I'm not too familiar with windows threading but things like OpenMP and OpenCL are crossplatform so...

 

You could implement a thread pool and use some kind of task based parallelism where you create tasks that are processed by the available threads in some kind of first come first serve fashion yourself. But OpenMP and OpenCL (i think) have implementations for task based parallelism built in out of the box (https://computing.llnl.gov/tutorials/openMP/#Task) which you could take advantage off.

 

Basically the idea is to create tasks consisting of rendering and handling game events and the free threads grab the tasks as they become available. The threads complete the tasks but don't exit, instead they go into a waiting state waiting for new tasks to become available.

Link to comment
https://linustechtips.com/topic/606000-c-threading-performance/#findComment-7850097
Share on other sites

Link to post
Share on other sites

https://m.reddit.com/r/gamedev/comments/207g2b/naughty_dog_lead_programmer_jason_gregory_talks/

 

Give that video a look over. He explains there threading system a bit. Essentially what you want to do is create a thread pool that has a queue of tasks. Each thread once finished a task grabs the next one in the queue.

CPU: Intel i7 - 5820k @ 4.5GHz, Cooler: Corsair H80i, Motherboard: MSI X99S Gaming 7, RAM: Corsair Vengeance LPX 32GB DDR4 2666MHz CL16,

GPU: ASUS GTX 980 Strix, Case: Corsair 900D, PSU: Corsair AX860i 860W, Keyboard: Logitech G19, Mouse: Corsair M95, Storage: Intel 730 Series 480GB SSD, WD 1.5TB Black

Display: BenQ XL2730Z 2560x1440 144Hz

Link to comment
https://linustechtips.com/topic/606000-c-threading-performance/#findComment-7851862
Share on other sites

Link to post
Share on other sites

42 minutes ago, trag1c said:

https://m.reddit.com/r/gamedev/comments/207g2b/naughty_dog_lead_programmer_jason_gregory_talks/

 

Give that video a look over. He explains there threading system a bit. Essentially what you want to do is create a thread pool that has a queue of tasks. Each thread once finished a task grabs the next one in the queue.

 

10 hours ago, Hamosch said:

All of my C/C++ experience is on *nix systems so I'm not too familiar with windows threading but things like OpenMP and OpenCL are crossplatform so...

 

You could implement a thread pool and use some kind of task based parallelism where you create tasks that are processed by the available threads in some kind of first come first serve fashion yourself. But OpenMP and OpenCL (i think) have implementations for task based parallelism built in out of the box (https://computing.llnl.gov/tutorials/openMP/#Task) which you could take advantage off.

 

Basically the idea is to create tasks consisting of rendering and handling game events and the free threads grab the tasks as they become available. The threads complete the tasks but don't exit, instead they go into a waiting state waiting for new tasks to become available.

Thank you guys, will check it out. Sorry for late reply.

~ Luc Luc

Link to comment
https://linustechtips.com/topic/606000-c-threading-performance/#findComment-7852001
Share on other sites

Link to post
Share on other sites

18 hours ago, Tornation said:

 

Thank you guys, will check it out. Sorry for late reply.

Starting/killing threads is very expensive, doing it 60 times a seconds is not efficient.

That way of threading only works when you have a ton to do in those threads so that the overhead of starting/killing threads is low compared to the total execution time of the program.

 

All modern game engines use some kind of task system (often using a task graph).

 

For a simple engines like yours you could consider:

 - start threads at start up

 - have a thread safe queue from which all worker threads get work when they're not doing anything

 - put tasks in the queue from the main thread

 

This is called the producer/consumer pattern.

Tasks would be structs containing a data pointer and a function pointer (which will get executed on the data).

Make sure that everything is thread safe and there are no race conditions.

More advanced systems let tasks spawn new tasks creating a graph.

One of the hardest parts is to make sure that graph gets executed as efficiently as possible.

 

There are a couple of good talks available from GDC vault for free:

http://www.gdcvault.com/play/1012321/Task-based-Multithreading-How-to (maybe a bit too old/outdated (2010), havent seen it myself)

http://www.gdcvault.com/play/1022106/Lessons-from-the-Core-Engine (destiny's multithreaded engine)

http://www.gdcvault.com/play/1021926/Destiny-s-Multithreaded-Rendering (more about destiny's multithreaded engine)

http://www.gdcvault.com/play/1022186/Parallelizing-the-Naughty-Dog-Engine (parallelizing the last of us engine for the PS4 remastered version, really good talk IMO)

 

Furthermore, I found this blog to be quite informative:

https://blog.molecular-matters.com

Desktop: Intel i9-10850K (R9 3900X died 😢 )| MSI Z490 Tomahawk | RTX 2080 (borrowed from work) - MSI GTX 1080 | 64GB 3600MHz CL16 memory | Corsair H100i (NF-F12 fans) | Samsung 970 EVO 512GB | Intel 665p 2TB | Samsung 830 256GB| 3TB HDD | Corsair 450D | Corsair RM550x | MG279Q

Laptop: Surface Pro 7 (i5, 16GB RAM, 256GB SSD)

Console: PlayStation 4 Pro

Link to comment
https://linustechtips.com/topic/606000-c-threading-performance/#findComment-7855731
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×