2012-01-30

Maya API and openMP multithreading

In this post I want to write about the steps necessary to compile a Maya plug-in, that uses openMP multithreading, with Visual Studio. I assume the reader has compiled a Maya plug-in before.

Summary:
  • Enable openMP option in project properties
  • Don't use Visual Studio Express/Standard
  • Switch to Release in "Solution Configuration" to use the plug-in (.mll) on other PCs

Detailed explanation:
Writing the code is fairly straightforward (it's not a lot) and the Autodesk Maya API Guide and Reference explain openMP really well. (Check out the splatDeformer devkit example)
Now I will write the steps necessary to get the splatDeformer running (I am using Visual Studio 2008 and Maya 2010, 2011, 2012 all 64bit):
  • Open the splatDeformer.sln in the Maya devkit folder (if you copy it somewhere else you have to fix the \lib and \include paths)
  • You should be able to compile the solution already. (If not, there is probably something non-openMP related not working)
  • It's compiling because openMP is actually disabled by default in the solution and the openMP code is not used. To enable it you have to set splatDeformer: Properties > Configuration Properties > C/C++ > Language > OpenMP Support > Yes (/openmp)
  • If you are using the Express or Standard edition of Visual Studio you will get the following error:
fatal error C1083: Cannot open include file: 'omp.h': No such file or directory
  • That's because the Express/Standard edition do not support openMP. You can find some tutorials on how to install openMP manually. But I can not confirm that they are working in this case, because I switched to the professional version at my school.
  • So with a Visual Studio version, that supports openMP, you should be able to compile the plug-in successfully. And maybe it will work on your PC, but most likely not on other PCs. The error should be:
Error: The application has failed to start because its side-by-side configuration is incorrect. Please see the application event log or use the command-line sxstrace.exe tool for more detail.
  • To fix this you have to switch your Visual Studio "Solution Configuration" from Debug to Release. (Note: Release may have different Configuration Properties, so you may have to enable OpenMP Support again and set output file, etc). More experienced Visual Studio users will know this error, because it also happens if you don't use the Release mode and try to load your output file with Maya on another PC (that does not have Visual Studio installed). More information on that point (bug report)

For a more complex deformer example than splatDeformer, that is using openMP, check out my prAttractNode. I noticed an increase in performance of 10-30% from openMP. You can find the open source download link in the Vimeo description of this video:

prAttractNode - deformer (Maya API, plug-in, Python)

6 comments:

  1. Hello.
    Great plugin, but with a traditional problem.
    Bad idea to use for(i) with weightValue(i) (openMP implementation).
    If you remove vertices from the "Deformer Set" indices change.
    MItGeometry skip some indices.
    I have not found a single example of the implementation without Maya iterator.
    Example: http://www.youtube.com/watch?v=spjOMpHTHrA
    Any ideas?

    ReplyDelete
    Replies
    1. Hi,
      thanks for the great feedback. I fixed it by storing the weight values outside of the loop. Just like the vertex positions. CreativeCrash is down at the moment, but I will update the files as soon as CreativeCrash is online again.

      Delete
    2. :) Cool. Thanks. I had thought about this method too, but I was hoping that you can to get the weight from MdataBlock or MPlug.
      I found that I had some problems in understanding Maya plug tree and how Maya stores data.
      I think that should be used MFnGeometryFilter, MFnWeightGeometryFilter and MFnSet, but I did not get...
      Sorry for my bad English.

      Delete
    3. Hey,
      actually I also did that for another plug-in, which is not finished, so I can't upload it yet. I had to do it with a custom paintable attribute. But I am not sure it is the proper way, because I could not find an online resource for reading paintable attributes and my Maya API understanding is still limited. For the default-deformer-weights attribute I would always recommend to use the convenient Maya API functions. Anyways here is the python api code, I hope it can help you (block and multiIndex are the deformer default arguments):

      ahFalloffWeightsList = block.inputArrayValue( self.aFalloffWeightList )
      ahFalloffWeightsList.jumpToArrayElement( multiIndex )
      hFalloffWeightsList = ahFalloffWeightsList.inputValue()
      hFalloffWeights = hFalloffWeightsList.child( self.aFalloffWeights )
      oFalloffWeights = hFalloffWeights.data()
      fnFalloffWeights = om.MFnDoubleArrayData( oFalloffWeights )
      arrayFalloffWeights = fnFalloffWeights.array()
      while not iter.isDone():
      falloffValue = arrayFalloffWeights[iter.index()]

      Delete
  2. Just for fun. Inside MpxDeformerNode::weightValue (OpenMayaAnim.dll)
    http://www.youtube.com/watch?v=BPM6dhswIVE
    We can see what functions are called.
    The use of an iterator (for get weights) is killing all the benefits of time.
    In my deformer weights getting time (with iterator) is equal to deformer calculation time.
    Will continue to think...

    ReplyDelete