XNA Creators Club Online
Page 1 of 1 (13 items)
Sort Posts: Previous Next

Threading: Is it possible to use multiple threads and multiple ContentManagers and avoid causing threading issues?

Last post 9/25/2009 5:52 PM by MrBubbas. 12 replies.
  • 9/21/2009 7:21 AM

    Threading: Is it possible to use multiple threads and multiple ContentManagers and avoid causing threading issues?

    I have a question regarding the thread safety and the ContentManager. Is it possible to load contents from a thread different from the thread that created the ContentManager and not end up in a world full of threading issues?

    To clarify: consider the following scenario:

    Note: The Game class is not used.

    At startup in Main thread:
    Create the graphics device
    Create 3 ContentManagers
    Create 2 worker threads

    During game loop:
    Main thread loads graphics assets from ContentManager1
    Worker thread 1 loads asset of type A from ContentManager2
    Worker thread 2 loads asset of type B from ContentManager3

    Main thread renders graphics assets
    Worker thread 1 uses asset of type A for doing whatever
    Worker thread 2 uses asset of type B for doing whatever

    Note: During the update there is no transfer of data between the threads.

    The reason for the question is:
    The ContentManager requires a IServiceProvider when created. But what happens if 2 different ContentManagers are called simultaneously from two differnet threads? Will there by threading issues due to they both being created using the same IServiceProvider?

    Best regards,
    Mr. Bubbas
  • 9/21/2009 12:09 PM In reply to

    Re: Threading: Is it possible to use multiple threads and multiple ContentManagers and avoid causing threading issues?

    All Content Managers do 'under the hood' is load the compiled .xnb files from the hard disk using the File System.

    You will certainly have problems trying to read files from more than one thread since File IO is exclusive to a single thread so you'll get thread locking issues. For example if thread #1 is reading some content, and then thread #2 tries to read some content, thread #2 will block until thread #1 has finished reading the content file. At least this is my understanding of what's going on.

    A much better idea would be to have all of your file loading on a separate thread from the main game loop, meaning your game can keep running whilst the content files are loaded in the background. You'd then only need to keep a mutex lock on your scene graph once you've loaded the content into memory and need to add it to the game.
    Graphics Programmer,Sandswept Studios.http://www.sandswept.net
  • 9/21/2009 12:53 PM In reply to

    Re: Threading: Is it possible to use multiple threads and multiple ContentManagers and avoid causing threading issues?

    zanders:
    All Content Managers do 'under the hood' is load the compiled .xnb files from the hard disk using the File System.

    You will certainly have problems trying to read files from more than one thread since File IO is exclusive to a single thread so you'll get thread locking issues. For example if thread #1 is reading some content, and then thread #2 tries to read some content, thread #2 will block until thread #1 has finished reading the content file. At least this is my understanding of what's going on.

    A much better idea would be to have all of your file loading on a separate thread from the main game loop, meaning your game can keep running whilst the content files are loaded in the background. You'd then only need to keep a mutex lock on your scene graph once you've loaded the content into memory and need to add it to the game.


    Ahhh...I totally missed the fact that FileIO is exclusive to one thread. This makes my question rather irrelevant. I'll take your advice on using only one thread for loading resources! The additional work of synchronizing multiple threads to avoid FileIO access stalls is far too much work to be worth implementing in the code I'm currently working on.
    Thanks for the advice!

    Best Regards,
    Mr. Bubbas
  • 9/21/2009 5:46 PM In reply to

    Re: Threading: Is it possible to use multiple threads and multiple ContentManagers and avoid causing threading issues?

    I totally missed the fact that FileIO is exclusive to one thread


    That's not actually true. The kernel is totally free to re-order I/O requests. And if you use BeginRead()/EndRead() to do asynchronous I/O, it's even very explicit that file I/O is threaded, because different worker threads will call your IAsyncResult completion function for different requests.

    However, that's not what causes problems with multi-threading loading. The problems are:

    1) The content manager uses a dictionary from string to asset, to return the same object the next time you ask for it, without going back to disk. This dictionary is not thread safe. I don't think the content manager wraps it in locks, either.

    2) The content manager has to create graphics resources when it loads textures and models. This calls into the graphics device. While the graphics device is somewhat thread safe for each individual call, depending on what the specifics of your content are (especially for custom content types), this may be a problem. Graphics device resets happening in the middle come to mind (only a PC problem, though).

    3) If you're loading from a DVD, the seek time is terrible. You really want to order all your loads to be sequential. While there may be multiple I/O requests outstanding, in the end, there is only a single laser reading the disk. For hard disks, depending on what your disk geometry looks like, you may get parallelism out of the disk(!) but that's only possible on PC, not on Xbox, which has a very low-end single hard drive set-up.

    So, putting I/O onto a separate thread to not block the main thread is a good idea, assuming you can manage the thread problems of the content manager dictionary and the graphics device. Spreading I/O across multiple threads is only a good idea if you have a studly I/O subsystem (which only happens on PCs, and only some PCs at that). However, if there is significant processing required as part of creating the asset (again, typically with custom assets), putting that processing onto separate threads will help parallelism.
    Jon Watte, Direct3D MVP
    Tweets, occasionally
    kW X-port 3ds Max .X exporter
    kW Animation source code
  • 9/22/2009 9:35 AM In reply to

    Re: Threading: Is it possible to use multiple threads and multiple ContentManagers and avoid causing threading issues?


    1) The content manager uses a dictionary from string to asset, to return the same object the next time you ask for it, without going back to disk. This dictionary is not thread safe. I don't think the content manager wraps it in locks, either.

    I looked at Shawn Hargreaves ppt presentation (Understanding XNA Framework Performance) from the 2008 GDC and he states that one should only create 1 ContentManager per thread. Could the dictionary issue be the reason for his advice? But if I made sure that only one WorkerThread accessed a particular ContentManager at any time during the gameloop there should not a problem (apart from the lost graphics device issue) ?!?

    So, putting I/O onto a separate thread to not block the main thread is a good idea, assuming you can manage the thread problems of the content manager dictionary and the graphics device.

    Have I understood You correct: It is legal to create a ContentManager in one thread and using it from another thread if special care is taken to ensure that the threads do not access the ContentManager at the same time?

    Best Regards,
    Mr. Bubbas
  • 9/22/2009 12:22 PM In reply to

    Re: Threading: Is it possible to use multiple threads and multiple ContentManagers and avoid causing threading issues?

    jwatte:
    if you use BeginRead()/EndRead() to do asynchronous I/O

    oops! Well you learn something new every day.. :S

    Looks like you should be able to get away with having multiple content managers with one for each thread... as long as they don't all load in parallel.
    Graphics Programmer,Sandswept Studios.http://www.sandswept.net
  • 9/22/2009 5:38 PM In reply to

    Re: Threading: Is it possible to use multiple threads and multiple ContentManagers and avoid causing threading issues?

    MrBubbas:
    he states that one should only create 1 ContentManager per thread. Could the dictionary issue be the reason for his advice?


    That's one reason. There are also various internal structures to do with instantiating ContentTypeReader worker objects.

    MrBubbas:
    Have I understood You correct: It is legal to create a ContentManager in one thread and using it from another thread if special care is taken to ensure that the threads do not access the ContentManager at the same time?


    Correct. This is always the case when a class is not thread safe: you can still use it from more than one thread as long as only one thread touches it at a time, and as long as you use proper thread synchronization constructs (for instance a lock statement or WaitHandle) to coordinate access to the object (some people try to coordinate access just using a boolean flag rather than a proper thread synchronisation technique, which is not robust because it does not insert the proper memory barriers when transferring ownership between the two threads).

    "not threadsafe" means "don't have more than one call into this object going on at the same time", not "can only ever access it from a single thread". It's fine for more than one thread to touch the same object, as long as they don't do this at the same time.
    XNA Framework Developer - blog - homepage
  • 9/22/2009 5:40 PM In reply to

    Re: Threading: Is it possible to use multiple threads and multiple ContentManagers and avoid causing threading issues?

    zanders:
    Looks like you should be able to get away with having multiple content managers with one for each thread... as long as they don't all load in parallel.


    Loading in parallel works fine if you want to do that, as long as you use multiple ContentManager instances.

    That said, I don't know why you would want to do this. It'll work, but it's likely to slow down rather than speed up your overall loading, because of the seek time issues Jon mentioned.
    XNA Framework Developer - blog - homepage
  • 9/22/2009 6:59 PM In reply to

    Re: Threading: Is it possible to use multiple threads and multiple ContentManagers and avoid causing threading issues?

    Thank you all for helping me figuring out the threading do's and dont's of the ContentManager!

    I think I've come up with a working solution for handling the ContentManager in my code. I'll create a ContentSystem that allows for IContentListener interfaces to register for loading of assets. Each IContentListener will get a dedicated ContentManager that resides inside the ContentSystem. Since the code I'm working on has a Compoenet Based "semi parallell" architecture the ContentSystem will work as follows:

    The basic game loop of the "Engine" is a follows:

    A number of ComponentSystems (each responsible for a particular Component) each gets updated in parallell by a number of worker threads.
    When all ComponentSystems have been updated, the main thread gathers any component information that has been updated and distributes it to "interested" ComponentSystems (ComponentSystems implementing IComponentListener). And then the  scheme repeats again and again. (very short explanation).

    During the distribution of Component changes the code is running on one thread only (Main Thread) and thus distribution is done serially. This is where IContentListener can request assets to be loaded by the ContentSystem. When the next update comes along a worker thread will update the ContentSystem and it will load the requested assets. When the next time comes for the Main thread to notify about component changes the code will run serially and the ComponentSystem will notify registered IContentListeners that the loaded assets have been loaded and are ready for pickup. The IContentListeners can then collect the loaded asstes before the engine runs the nex parallell update.

    That's the main idea anyway. It fits quite nice into the original architecture. What remains to test is wheter it will bog down the engine or not. I believe the time spent in serial mode (running on Main Thread only) should be kept to a minimum.

    Keeping my fingers crossed, I'll implement this idea and see where it leads. If its totally c**p then atleast I know one idea that didn't quite do the trick :)

    Best Regards,
    Mr. Bubbas



  • 9/24/2009 11:32 PM In reply to

    Re: Threading: Is it possible to use multiple threads and multiple ContentManagers and avoid causing threading issues?

    In my game, I loaded the first level at loadContent(), then immediately after, I called to get the next level ready in another thread. This meant that the user would never be waiting for the next level to load.
  • 9/24/2009 11:39 PM In reply to

    Re: Threading: Is it possible to use multiple threads and multiple ContentManagers and avoid causing threading issues?

    Remember that if you are targetting xbox you'll have to set cpu affinity because its scheduler doesn't dynamically move the threads from processor to processor.
    I'm too busy writing computer graphics for my day job to have any games in play-test or peer-review.
    Twitter: twitter/guysherman
    Blog: www.guysherman.com
  • 9/25/2009 4:16 PM In reply to

    Re: Threading: Is it possible to use multiple threads and multiple ContentManagers and avoid causing threading issues?

    I don't quite get the one ContentManager per Thread recommendation. Is it only that, a recommendation, or can bad things happen?

    Assume I created a ContentManager to load and keep the resources I need for a single level in my game, which I then Dispose() of when another level needs to be loaded. Since the Game class also instantiates a ContentManager by default, I would now have 2 ContentManagers in my main thread. Would that already mean leaving the area of safety and entering undefined behavior land?
    Check out my website and blog for some interesting articles and useful utility classes!
    Nuclex Framework: threaded particles, skinnable GUI, vector fonts, texture atlasses and lots more.
    WiX XNA Installer: Professional-looking MSI installer template for XNA games.
  • 9/25/2009 5:52 PM In reply to

    Re: Threading: Is it possible to use multiple threads and multiple ContentManagers and avoid causing threading issues?

    DynamicSamurai:
    Remember that if you are targetting xbox you'll have to set cpu affinity because its scheduler doesn't dynamically move the threads from processor to processor.


    Yepp I know :)

    Best Regards,
    Mr. Bubbas 
Page 1 of 1 (13 items) Previous Next