Problems with Matlab parfor data disappearing

I work a lot in Matlab at work, and Matlab’s object-oriented capabilities in particular.  I encountered a problem that took me a couple hours to debug, and hopefully I can help someone else avoid the experience.

I had my code set up to use a regular for loop when processing serially and a parfor loop when processing with a Matlab pool.  The code worked fine in the serial case, but when using parfor, some of my objects’ properties seemed to be vanishing into empty matrices.  Very literally, one line before the parfor, the object had correctly populated data, and one line within the parfor that data was gone.  No errors from Matlab except errors later on down the road caused from the property being empty.  No indication of what was going on.  No luck finding solutions online.

If you find this happening, the problem is likely with the saving and loading of your object.  Matlab communicates data to each matlab pool worker by serializing the objects, which essentially means saving them in the client thread and having each worker load it back up.  If your object doesn’t save and load correctly, then it won’t get into the parfor loop correctly.

To test the saving and loading, construct an object of the class that’s giving you problems, save it, clear your workspace, then load it.  Inspect the object for missing or incorrect properties.  If you see a problem with a property, check to see if it has a custom set method defined, comment it out, save the updates (and remember to clear classes), and try again.  You should see the data is no longer corrupted.

So what’s happening here?  When Matlab loads objects (either from a mat file or through serialization), it invokes the set method for all properties being loaded.  If an error occurs in a set method during this process, Matlab gives up on setting that property, provides no notice that an error occurred, and just leaves it as the default specified for that property.  Unless your properties block in the classdef says otherwise, the default value for the property will be an empty matrix.

(I have also had problems with handle objects getting into and out of parfor loops, but that wasn’t the problem here.)

In my case, the error I was getting was due to a self-consistency check in my set method.  Before setting the property A, I check to make sure that it is consistent with some other property B.  However, property A was being loaded before property B, so the consistency check always failed on load.  I worked around this by checking to make sure property B was non-empty before doing the consistency check.  This didn’t pose any problems for my class because in normal usage, my property B must always be defined before property A.  Unfortunately, this wasn’t the case when loading or serializing.

An Aside on Set Methods and Loading

In my experience with Matlab OOP, the automatic invoking of set methods on load or serialization has been a significant headache.  As far as I know, the main reason for doing this is so the class version can be checked, and the loaded property modified if necessary to maintain backwards compatibility.  In my experience, I use set methods almost exclusively for type checking and consistency checks on inputs, so any object that doesn’t throw an error has an allowable state, is saved in that allowable state, and should be loaded in that allowable state.  Checking the state again when loading by invoking the set methods is not needed for my uses, and has caused me headaches such as the one outlined above on more than one occasion.

Admittedly, Matlab’s mlint says that you shouldn’t reference one property from another property’s set method.  While I usually follow mlint’s suggestions, this is one I ignore outright as it significantly reduces the utility of set methods in my opinion.  Having users set properties in a natural way, and having the set methods automatically check the correctness of those properties, is by far the best use of set methods I can think of.  If anyone knows of a better way to achieve the same functionality, or a better reason to use set methods, I would love to hear it and learn more.