Material Need to Load lots of data

Discussion related to the LuxRender Material system, programming API and Scene file format.

Moderators: jromang, tomb, zcott, coordinators

Material Need to Load lots of data

Postby Olliebrown » Mon Jan 16, 2012 3:18 pm

I have a material that is based on lots of data stored on the disk (over 100mb compressed). At present, I load this data in the constructor of the material but this is creating a bit of a bottleneck when I start-up a networked render. It goes something like this:

- Local luxrender client loads all the files
- Sends scene to first server and waits while it loads all the files
- Sends scene to second server and waits while it loads
- etc.

All this waiting while the servers are loading the data seems inefficient and makes for a long startup time. I'm wondering if I could just do it somewhere else in the material class so that it doesn't happen while the server is receiving commands from the client. If it could wait and happen after the client finishes sending the scene and has moved to the next server (or started rendering itself) that would be super. Perhaps it could just wait until the material is used in some way but I don't know where in the code I could recognize this situation. Perhaps things need to happen in the BxDF class that drives this material instead of the material class but I'm just guessing and could use some guidance.

I thought about doing the data loading inside of GetBSDF() but I quickly noticed that this function is const and naturally I need to modify the object when I load the data. I'm also concerned about threading here. My thought was just to protect this data loading code with a mutex (and also some flag to make sure it doesn't try and load it twice).

Right now, the material object stores all the data and passes a pointer to all this data into the BxDF as it gets created in GetBSDF(). I allocate a new BxDF every time GetBSDF() gets called but reuse the data stored in the Material object. This was based on looking at other material classes and their GetBSDF() functions so if there's a better way to do it that would help my situation (i.e. make the BxDF once, maybe the first time GetBSDF() is called then send the same one on subsequent GetBSDF() calls) I'm all for it! This would allow me to read the data in the BxDF instead of the material and likely solve my problem. It's a significant change though and intuition says it will F-up the whole material class/BSDF hierarchy if they are all using the same BxDF instead of independent instances. So I'm asking first rather than trying first.

Thanks!
Seth
Olliebrown
 
Posts: 53
Joined: Wed Nov 04, 2009 9:15 pm

Re: Material Need to Load lots of data

Postby Lord Crc » Mon Jan 16, 2012 6:14 pm

The first and easiest (relatively) optimization would be to make the master send out the scene to all slaves in parallel. I think this would solve a fair chunk of your problem. It's already a feature request in the bugtracker.

However you should be able to do some delayed loading. Keep a flag which indicates if the material is loaded or not, and check it in GetBSDF. If it's false, acquire a lock and check the flag again to check if another thread performed the load while you waited for the mutex. If still not loaded, perform the load and set the flag. Something like this:
Code: Select all
// in .h file
class MyMaterial : Material
{
...
private:
  void loadData();

  bool initialized;
  boost::mutex initMutex;
}

BSDF *MyMaterial::GetBSDF(MemoryArena &arena, const SpectrumWavelengths &sw,
   const Intersection &isect, const DifferentialGeometry &dgs) const
{
  if (!initialized) {
     boost::mutex::scoped_lock  initLock(initMutex);
     // check if another thread performed initialization while current thread waited
     if (!initialized) {     
       loadData();
       initialized = true;
     } // else initialized, all good
  }

  ...
  return bsdf;
}
May contain traces of nuts.
User avatar
Lord Crc
Developer
 
Posts: 4446
Joined: Sat Nov 17, 2007 2:10 pm

Re: Material Need to Load lots of data

Postby Olliebrown » Mon Jan 16, 2012 9:13 pm

That's the first approach I tried; thnk you for the code by the way! It shows me how to use the boost::mutex which I was going to have to figure out.

The problem I run into with that approach is that GetBSDF() is marked const. Unfortunately my loadData() is not const and can't be as it allocates memory to store what's being read into a member variable. Maybe I can find some way To allocate that memory in the constructor so that LoadData can be const. It would be possible as presently the data is of a fixed and known size but it might not be in the future. For now, it seems like the best solution!

Thanks :D

Seth
Olliebrown
 
Posts: 53
Joined: Wed Nov 04, 2009 9:15 pm

Re: Material Need to Load lots of data

Postby Lord Crc » Mon Jan 16, 2012 10:36 pm

Just set the data field as mutable in the class definition, fex

Code: Select all
// in .h file
class MyMaterial : Material
{
...
private:
  void loadData();

  mutable float* my_data; // loadData fills this
  bool initialized;
  boost::mutex initMutex;
}


This makes it possible to change it even in const methods. It's a bit dirty but as you say, easy to implement.
May contain traces of nuts.
User avatar
Lord Crc
Developer
 
Posts: 4446
Joined: Sat Nov 17, 2007 2:10 pm

Re: Material Need to Load lots of data

Postby Olliebrown » Tue Jan 17, 2012 12:12 am

Wow, that is a keyword I did not know about. Thought I had seen it all but I guess C++ is just too big for that. At least I'm down to only about 1 unknown, obscure keyword a year (last year's was 'explicit').

That seems to have done it. Now it waits until after the scene gets passed around and then they all load the data in parallel at the start of the render. Had to make the mutex and the initialized flag mutable too (plus a few other members used for caching the data so other instances of the same material don't have to re-read the file). But they're all private members so it really shouldn't matter anyways.

Thanks for all the help!

Seth
Olliebrown
 
Posts: 53
Joined: Wed Nov 04, 2009 9:15 pm

Re: Material Need to Load lots of data

Postby Lord Crc » Tue Jan 17, 2012 12:59 am

Olliebrown wrote:Wow, that is a keyword I did not know about. Thought I had seen it all but I guess C++ is just too big for that. At least I'm down to only about 1 unknown, obscure keyword a year (last year's was 'explicit').


Hehe, know the feeling ;) I've learned a lot of C++ after I started working on LuxRender. Then again I hadn't written any C++ before that, but I had read a lot.

Olliebrown wrote:Had to make the mutex and the initialized flag mutable too (plus a few other members used for caching the data so other instances of the same material don't have to re-read the file). But they're all private members so it really shouldn't matter anyways.


Doh yes, of course.

Glad it worked, and hope you can share the end results, curious what you're doing with all that data ;)
May contain traces of nuts.
User avatar
Lord Crc
Developer
 
Posts: 4446
Joined: Sat Nov 17, 2007 2:10 pm


Return to Materials, API & Scene file format

Who is online

Users browsing this forum: No registered users and 1 guest