In general it is not safe to assume any Maya API is threadsafe if it is not documented as being so. There can be internal caching or state being set, meaning functions that may seem threadsafe are in fact not. An example is MFnMesh::getVertexNormal(). These normals are evaluated lazily, meaning the first call to this function may trigger a full recompute of all normals, so two calls simultaneously may have bad consequences. One clunky way around this is to do one dummy call first to ensure the data is up to date. After that parallel queries should be fine. But I would not recommend anyone to depend on that behavior as Maya implementation may change in future and that trick might not work anymore. People in Maya engineering who nicely reviewed that post for me (thx to them :), are actively working on improving Maya's performances and their work may impact how things work internally. For that reason just assume none of these API are threadsafe and instead you should stick to what is explicitly documented as being threadsafe.
If you want to do intersection operations, note that the closest point and intersect methods on MFnMesh are not threadsafe. However MMeshIntersector is threadsafe. Intersection operations on Nurbs and Subdivs are also not threadsafe.
The MPoint/MVector/MMatrix/MArray classes are thread-safe only in the sense that simultaneous accesses to distinct objects are safe, and simultaneous read accesses to shared objects are safe. If multiple threads access a single object, and at least one thread may potentially write, then the user is responsible for ensuring mutual exclusion between the threads during the object accesses.
In terms of APIs, it is fine to use any threading API including native threads (pthreads/win32), OpenMP, or TBB. In Maya 2008, we added a threading API. (See classes MThreadPool, MThreadAsync, MMutexLock, MSpinLock, and example plug-ins threadTestCmd, threadTestWithLocksCmd). This API is designed to mimic a native threading API like pthreads/win32 threads, so existing code using native threads can be migrated over to it. The benefit of using the Maya API is that the code is run using the existing internal Maya thread pool. These internal threads respect thread count controls in Maya (eg the threadCount command) and also handle nested threading.
The latter point means that it is possible to invoke a threaded region from inside another threaded region without causing oversubscription, as the threads are managed by a task manager (actually it is based on Intel's Threading Building Blocks technology). You do not have to use the Maya threading API, but if you don't you should ensure that the plug-in respects the current Maya thread count. (The MEL command "threadCount -q -n" will return the current number of threads to be used). This ensures that if the user wants to run multiple Maya sessions at the same time in single threaded mode, eg for rendering, your plug-in will play nice and also run single threaded. In general, use TBB for parallel complex situation in your code. Your TBB code will play nicely in the Maya threading environment as Maya TBB core will manager your threads as if they were Maya’s. But, I would recommend you to be careful when using TBB for some fairly easy loops as TBB may not necessarily give you better results than single threaded code.
Intel's TBB is the recommended alternative for Maya over all multithreading options you have, and it is used internally in Maya. There should be no problem writing plug-ins using this API, but it is best to use the same version as that being used by Maya (versions available on that post). It supports nested threading, and also provides a variety of threadsafe containers and a thread-aware memory allocator. Any comments or suggestions welcome - we want to make it as easy as possible to write multithreaded plug-ins for Maya without forcing you into one particular API or methodology.
We would recommend using Intel's TBB over OpenMP for these reasons:
- The Intel's TBB library has a broader scope of functionality that OpenMP.
- It's a library only implementation, so it does not depend on the compiler support "special" pragmas.
- In recent Maya development, we have been using almost exclusively TBB internally (because of point 1 and 2) to multi-thread parts of Maya. So, indirectly using Intel TBB in Maya has been empirically proven…
The advantage of OpenMP is that it is often simpler to use for simple cases. For example, parallelizing a loop often amounts to adding a single pragma. But, for slightly more complex cases TBB wins (tasks, thread-safe containers, locks, etc...).
Note that OpenMP is fine as well, but not recommended. It is an easy way to add data parallelism to a plug-in. Internally Maya uses the Intel OpenMP library on all platforms as we have found it delivers very good performance, but it should be ok to use the VC++ version as well. Just be sure to be consistent, i.e. do not mix compilers where OpenMP constructs are implemented in each, since an OpenMP region declared by the Intel compiler will ignore any OpenMP locks declared by the Microsoft compiler and vice versa. If using VC++ OpenMP you again need to keep the thread count in sync with Maya. With the Intel compiler this is not necessary as Maya manages it internally.
This article has been inspired by Martin Watt' whitepaper available here.
Comments
You can follow this conversation by subscribing to the comment feed for this post.