Add new mju_threadpool API function, and delete old threading API.

PiperOrigin-RevId: 922838541
Change-Id: Id9f7e0fb298ffde61fcc49a802dc78971858ce51
This commit is contained in:
Kyle Bayes
2026-05-28 10:09:07 -07:00
committed by Copybara-Service
parent a22fc2423a
commit b935d4153c
47 changed files with 576 additions and 1755 deletions
-4
View File
@@ -452,10 +452,6 @@ indicated otherwise.
* - ``mjMINAWAKE``
- 10
- The minimum number of timesteps that must pass after a tree is awoken, before it is allowed to go back to sleep.
* - ``mjMAXTHREAD``
- 128
- Maximum number of OS threads that can be used in a thread pool.
Defined in `mjthread.h <https://github.com/google-deepmind/mujoco/blob/main/include/mujoco/mjthread.h>`_.
.. _glNumericSizes:
-30
View File
@@ -1013,36 +1013,6 @@ Asset cache used by the compiler to avoid repeated slow recompilation. See :ref:
.. mujoco-include:: mjCache
.. _mjtTaskStatus:
mjtTaskStatus
~~~~~~~~~~~~~
Status values for :ref:`mjTask`.
.. mujoco-include:: mjtTaskStatus
.. _mjTask:
mjTask
~~~~~~
This is a representation of a task to be run asynchronously inside of an :ref:`mjThreadPool` . It is created in the
:ref:`mju_threadPoolEnqueue` method of the :ref:`mjThreadPool` and is used to join the task at completion.
The ``status`` field uses values from :ref:`mjtTaskStatus`.
.. mujoco-include:: mjTask
.. _mjThreadPool:
mjThreadPool
~~~~~~~~~~~~
This is the data structure of the threadpool. It can only be constructed programmatically, and does not
have an analog in MJCF. In order to enable multi-threaded calculations, a pointer to an existing :ref:`mjThreadPool`
should be assigned to the ``mjData.threadpool``.
.. mujoco-include:: mjThreadPool
.. _tyStatStructure:
+5 -50
View File
@@ -3375,59 +3375,14 @@ If no match, return NULL.
Threads
^^^^^^^
.. _mju_threadPoolCreate:
.. _mju_threadpool:
`mju_threadPoolCreate <#mju_threadPoolCreate>`__
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`mju_threadpool <#mju_threadpool>`__
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. mujoco-include:: mju_threadPoolCreate
.. mujoco-include:: mju_threadpool
Create a thread pool with the specified number of threads running.
.. _mju_bindThreadPool:
`mju_bindThreadPool <#mju_bindThreadPool>`__
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. mujoco-include:: mju_bindThreadPool
Adds a thread pool to mjData and configures it for multi-threaded use.
.. _mju_threadPoolEnqueue:
`mju_threadPoolEnqueue <#mju_threadPoolEnqueue>`__
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. mujoco-include:: mju_threadPoolEnqueue
Enqueue a task in a thread pool.
.. _mju_threadPoolDestroy:
`mju_threadPoolDestroy <#mju_threadPoolDestroy>`__
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. mujoco-include:: mju_threadPoolDestroy
Destroy a thread pool.
.. _mju_defaultTask:
`mju_defaultTask <#mju_defaultTask>`__
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. mujoco-include:: mju_defaultTask
Initialize an mjTask.
.. _mju_taskJoin:
`mju_taskJoin <#mju_taskJoin>`__
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. mujoco-include:: mju_taskJoin
Wait for a task to complete.
Create a thread pool with nthread worker threads.
.. _Standardmath:
+11 -1
View File
@@ -10,6 +10,16 @@ General
- Added :ref:`mjs_makeFlex`, a new C API function equivalent to the :ref:`flexcomp<body-flexcomp>` element for
programmatically creating flex objects with auto-generated bodies, joints, and equality constraints. Exposed as
``body.make_flex()`` in Python.
- Added :ref:`mju_threadpool`, a new function for creating a thread pool on an ``mjData`` instance. When a thread pool
is initialized, parts of the simulation pipeline, such as collision detection and constraint solving across islands,
are parallelized. The thread pool is automatically destroyed when the ``mjData`` is freed.
.. admonition:: Breaking API changes
:class: attention
- The header file ``mjthread.h`` was removed along with the engine threading API.
**Migration:** Use :ref:`mju_threadpool` to set number of worker threads for the engine.
Bug fixes
^^^^^^^^^
@@ -1708,7 +1718,7 @@ New features
If island discovery is enabled, geoms, contacts and tendons will be colored according to the corresponding island,
see video. Island discovery is currently disabled for models that have deformable objects (see previous item).
5. Added :ref:`mjThreadPool` and :ref:`mjTask` which allow for multi-threaded operations within the MuJoCo engine
5. Added ``mjThreadPool`` and ``mjTask`` which allow for multi-threaded operations within the MuJoCo engine
pipeline. If engine-internal threading is enabled, the following operations will be multi-threaded:
- Island constraint resolution, if island discovery is :ref:`enabled<option-flag-island>` and the
+5 -25
View File
@@ -89,9 +89,12 @@ struct mjData_ {
// arena pointer
size_t parena; // first available byte in arena
// threading
uintptr_t threadpool; // thread pool pointer
mjtBool threadlock; // disable stack freeing during threaded execution
// memory utilization statistics
mjtSize maxuse_stack; // maximum stack allocation in bytes (mutable)
mjtSize maxuse_threadstack[mjMAXTHREAD]; // maximum stack allocation per thread in bytes
mjtSize maxuse_arena; // maximum arena allocation in bytes
int maxuse_con; // maximum number of contacts
int maxuse_efc; // maximum number of scalar constraints
@@ -394,9 +397,6 @@ struct mjData_ {
mjtNum* efc_force; // constraint force in constraint space (nefc x 1)
mjtNum* ifrc_constraint; // constraint force (nidof x 1)
// thread pool pointer
uintptr_t threadpool;
// compilation signature
uint64_t signature; // also held by the mjSpec that compiled the model
};
@@ -2146,21 +2146,6 @@ typedef struct mjsDefault_ { // default specification
mjsTendon* tendon; // tendon defaults
mjsActuator* actuator; // actuator defaults
} mjsDefault;
typedef enum mjtTaskStatus_ { // status values for mjTask
mjTASK_NEW = 0, // newly created
mjTASK_QUEUED, // enqueued in a thread pool
mjTASK_COMPLETED // completed execution
} mjtTaskStatus;
struct mjThreadPool_ {
int nworker; // number of workers in the pool
};
typedef struct mjThreadPool_ mjThreadPool;
struct mjTask_ { // a task that can be executed by a thread pool.
mjfTask func; // pointer to the function that implements the task
void* args; // arguments to func
volatile int status; // status of the task
};
typedef struct mjTask_ mjTask;
typedef enum mjtDisableBit_ { // disable default feature bitflags
mjDSBL_CONSTRAINT = 1<<0, // entire constraint solver
mjDSBL_EQUALITY = 1<<1, // equality constraints
@@ -3658,12 +3643,7 @@ void mju_getResourceDir(mjResource* resource, const char** dir, int* ndir);
int mju_isModifiedResource(const mjResource* resource, const char* timestamp);
mjSpec* mju_decodeResource(mjResource* resource, const char* content_type,
const mjVFS* vfs);
mjThreadPool* mju_threadPoolCreate(size_t number_of_threads);
void mju_bindThreadPool(mjData* d, void* thread_pool);
void mju_threadPoolEnqueue(mjThreadPool* thread_pool, mjTask* task);
void mju_threadPoolDestroy(mjThreadPool* thread_pool);
void mju_defaultTask(mjTask* task);
void mju_taskJoin(mjTask* task);
void mju_threadpool(mjData* d, int nthread);
mjsElement* mjs_attach(mjsElement* parent, const mjsElement* child,
const char* prefix, const char* suffix);
mjsBody* mjs_addBody(mjsBody* body, const mjsDefault* def);
+2 -5
View File
@@ -31,9 +31,8 @@ OpenGL renderer
state-of-the-art rendering engines (and can be replaced with such an engine if desired) but nevertheless it provides
efficient and informative 3D rendering.
Thread
The threading framework is written in C++ and exposed in C. It provides a :ref:`mjThreadPool<mjThreadPool>` interface
to process tasks asynchronously. To enable use in MuJoCo, create a thread pool and assign it to the
``mjData.threadpool`` field.
The threading framework is written in C++ and exposed in C. It provides a thread pool interface
to process tasks asynchronously. To enable use in MuJoCo, call ``mju_threadpool``.
UI framework
The UI framework is written in C. UI elements are rendered in OpenGL. It has its own event
mechanism and abstract hooks for keyboard and mouse input. The code samples use it with GLFW, but it can also be used
@@ -171,8 +170,6 @@ links below, to make this documentation self-contained.
Defines enums and structs used for :doc:`procedural model editing <modeledit>`.
`mjplugin.h <https://github.com/google-deepmind/mujoco/blob/main/include/mujoco/mjplugin.h>`__
Defines data structures required by :ref:`engine plugins<exPlugin>`.
`mjthread.h <https://github.com/google-deepmind/mujoco/blob/main/include/mujoco/mjthread.h>`__
Defines data structures and functions required by :ref:`thread<Thread>`.
`mjmacro.h <https://github.com/google-deepmind/mujoco/blob/main/include/mujoco/mjmacro.h>`__
Defines C macros that are useful in user code.
`mjxmacro.h <https://github.com/google-deepmind/mujoco/blob/main/include/mujoco/mjxmacro.h>`__
+1 -1
View File
@@ -60,7 +60,7 @@ Where the command line arguments are
keyframe named "test" is present in the model, it is used as the initial state.
- The ``ctrlnoise`` argument prevents models from settling into a static state where, due to warmstarts, one can
measure artificially faster simulation.
- When ``npoolthread > 1`` is specified, an engine-internal :ref:`mjThreadPool` is created with the specified number of
- When ``npoolthread > 1`` is specified, an engine-internal thread pool is created with the specified number of
threads, to speed up simulation of large scenes. Note that while it is possible to use both ``nthread`` and
``npoolthread``, the scenarios for which one would want these different types of multithreading are usually mutually
exclusive.
+3 -4
View File
@@ -562,10 +562,9 @@ external force computed by inverse dynamics.
Multi-threading
~~~~~~~~~~~~~~~
MuJoCo has experimental support for within-step multi-threading. When a :ref:`mjThreadPool` is assigned to
``mjData.threadpool``, parts of the simulation pipeline — such as collision detection and constraint solving across
:ref:`islands<siSleep>` — can be distributed across worker threads. Note that within-step threading currently has
significant memory overhead and is still a work in progress.
MuJoCo has support for within-step multi-threading. When a thread pool is initialized via
``mju_threadpool``, parts of the simulation pipeline — such as collision detection and constraint solving across
:ref:`islands<siSleep>` — can be distributed across worker threads.
The more common and well-supported use of multi-threading is to speed up sampling operations that are
common in more advanced applications. Simulation is inherently serial over time (the output of one mj_step is the