diff --git a/doc/APIreference/APIglobals.rst b/doc/APIreference/APIglobals.rst index 6bb4726e..8a6502d1 100644 --- a/doc/APIreference/APIglobals.rst +++ b/doc/APIreference/APIglobals.rst @@ -489,6 +489,10 @@ shown in the table below. Their names are in the format ``mjKEY_XXX``. They corr - 1000 - Maximum number of textures allowed. Defined in `mjrender.h `_. + * - ``mjMAXTHREADS`` + - 128 + - Maximum number OS threads that can be used in a thread pool. + Defined in `mjthread.h `_. * - ``mjMAXUISECT`` - 10 - Maximum number of UI sections. diff --git a/doc/includes/references.h b/doc/includes/references.h index c17dad69..cfc186f6 100644 --- a/doc/includes/references.h +++ b/doc/includes/references.h @@ -136,10 +136,11 @@ struct mjData_ { size_t parena; // first available byte in arena // memory utilization stats - size_t maxuse_stack; // maximum stack allocation - size_t maxuse_arena; // maximum arena allocation - int maxuse_con; // maximum number of contacts - int maxuse_efc; // maximum number of scalar constraints + size_t maxuse_stack; // maximum stack allocation in bytes + size_t maxuse_threadstack[mjMAXTHREADS]; // maximum stack allocation per thread in bytes + size_t maxuse_arena; // maximum arena allocation in bytes + int maxuse_con; // maximum number of contacts + int maxuse_efc; // maximum number of scalar constraints // diagnostics mjWarningStat warning[mjNWARNING]; // warning statistics diff --git a/include/mujoco/mjdata.h b/include/mujoco/mjdata.h index 5f4124f3..c705ffab 100644 --- a/include/mujoco/mjdata.h +++ b/include/mujoco/mjdata.h @@ -20,6 +20,7 @@ #include #include +#include //---------------------------------- primitive types (mjt) ----------------------------------------- @@ -163,10 +164,11 @@ struct mjData_ { size_t parena; // first available byte in arena // memory utilization stats - size_t maxuse_stack; // maximum stack allocation - size_t maxuse_arena; // maximum arena allocation - int maxuse_con; // maximum number of contacts - int maxuse_efc; // maximum number of scalar constraints + size_t maxuse_stack; // maximum stack allocation in bytes + size_t maxuse_threadstack[mjMAXTHREADS]; // maximum stack allocation per thread in bytes + size_t maxuse_arena; // maximum arena allocation in bytes + int maxuse_con; // maximum number of contacts + int maxuse_efc; // maximum number of scalar constraints // diagnostics mjWarningStat warning[mjNWARNING]; // warning statistics diff --git a/include/mujoco/mjthread.h b/include/mujoco/mjthread.h index c716e70f..9a526fa5 100644 --- a/include/mujoco/mjthread.h +++ b/include/mujoco/mjthread.h @@ -15,6 +15,8 @@ #ifndef MUJOCO_INCLUDE_MJTHREAD_H_ #define MUJOCO_INCLUDE_MJTHREAD_H_ +#define mjMAXTHREADS 128 // maximum number of threads in a thread pool + typedef enum mjtTaskStatus_ { // status values for mjTask mjTASK_NEW = 0, // newly created mjTASK_QUEUED, // enqueued in a thread pool diff --git a/include/mujoco/mjxmacro.h b/include/mujoco/mjxmacro.h index e3dcae9f..67909b36 100644 --- a/include/mujoco/mjxmacro.h +++ b/include/mujoco/mjxmacro.h @@ -652,14 +652,15 @@ // vector fields of mjData -#define MJDATA_VECTOR \ - X( mjWarningStat, warning, mjNWARNING, 1 ) \ - X( mjTimerStat, timer, mjNTIMER, 1 ) \ - X( mjSolverStat, solver, mjNILSAND, mjNSOLVER ) \ - X( int, solver_niter, mjNISLAND, 1 ) \ - X( int, solver_nnz, mjNISLAND, 1 ) \ - X( mjtNum, solver_fwdinv, 2, 1 ) \ - X( mjtNum, energy, 2, 1 ) +#define MJDATA_VECTOR \ + X( size_t, maxuse_threadstack, mjMAXTHREADS, 1 ) \ + X( mjWarningStat, warning, mjNWARNING, 1 ) \ + X( mjTimerStat, timer, mjNTIMER, 1 ) \ + X( mjSolverStat, solver, mjNILSAND, mjNSOLVER ) \ + X( int, solver_niter, mjNISLAND, 1 ) \ + X( int, solver_nnz, mjNISLAND, 1 ) \ + X( mjtNum, solver_fwdinv, 2, 1 ) \ + X( mjtNum, energy, 2, 1 ) // alias XMJV to be the same as X diff --git a/introspect/enums.py b/introspect/enums.py index 44935c8a..52a9e391 100644 --- a/introspect/enums.py +++ b/introspect/enums.py @@ -370,6 +370,16 @@ ENUMS: Mapping[str, EnumDecl] = dict([ ('mjLRMODE_ALL', 3), ]), )), + ('mjtTaskStatus', + EnumDecl( + name='mjtTaskStatus', + declname='enum mjtTaskStatus_', + values=dict([ + ('mjTASK_NEW', 0), + ('mjTASK_QUEUED', 1), + ('mjTASK_COMPLETED', 2), + ]), + )), ('mjtState', EnumDecl( name='mjtState', @@ -633,16 +643,6 @@ ENUMS: Mapping[str, EnumDecl] = dict([ ('mjFONT_BIG', 2), ]), )), - ('mjtTaskStatus', - EnumDecl( - name='mjtTaskStatus', - declname='enum mjtTaskStatus_', - values=dict([ - ('mjTASK_NEW', 0), - ('mjTASK_QUEUED', 1), - ('mjTASK_COMPLETED', 2), - ]), - )), ('mjtButton', EnumDecl( name='mjtButton', diff --git a/introspect/structs.py b/introspect/structs.py index f4bcd560..2ddbfebb 100644 --- a/introspect/structs.py +++ b/introspect/structs.py @@ -3324,6 +3324,42 @@ STRUCTS: Mapping[str, StructDecl] = dict([ ), ), )), + ('mjThreadPool', + StructDecl( + name='mjThreadPool', + declname='struct mjThreadPool_', + fields=( + StructFieldDecl( + name='nworker', + type=ValueType(name='int'), + doc='number of workers in the pool', + ), + ), + )), + ('mjTask', + StructDecl( + name='mjTask', + declname='struct mjTask_', + fields=( + StructFieldDecl( + name='func', + type=ValueType(name='mjfTask'), + doc='pointer to the function that implements the task', + ), + StructFieldDecl( + name='args', + type=PointerType( + inner_type=ValueType(name='void'), + ), + doc='arguments to func', + ), + StructFieldDecl( + name='status', + type=ValueType(name='int', is_volatile=True), + doc='status of the task', + ), + ), + )), ('mjContact', StructDecl( name='mjContact', @@ -3541,12 +3577,20 @@ STRUCTS: Mapping[str, StructDecl] = dict([ StructFieldDecl( name='maxuse_stack', type=ValueType(name='size_t'), - doc='maximum stack allocation', + doc='maximum stack allocation in bytes', + ), + StructFieldDecl( + name='maxuse_threadstack', + type=ArrayType( + inner_type=ValueType(name='size_t'), + extents=(128,), + ), + doc='maximum stack allocation per thread in bytes', ), StructFieldDecl( name='maxuse_arena', type=ValueType(name='size_t'), - doc='maximum arena allocation', + doc='maximum arena allocation in bytes', ), StructFieldDecl( name='maxuse_con', @@ -7020,42 +7064,6 @@ STRUCTS: Mapping[str, StructDecl] = dict([ ), ), )), - ('mjThreadPool', - StructDecl( - name='mjThreadPool', - declname='struct mjThreadPool_', - fields=( - StructFieldDecl( - name='nworker', - type=ValueType(name='int'), - doc='number of workers in the pool', - ), - ), - )), - ('mjTask', - StructDecl( - name='mjTask', - declname='struct mjTask_', - fields=( - StructFieldDecl( - name='func', - type=ValueType(name='mjfTask'), - doc='pointer to the function that implements the task', - ), - StructFieldDecl( - name='args', - type=PointerType( - inner_type=ValueType(name='void'), - ), - doc='arguments to func', - ), - StructFieldDecl( - name='status', - type=ValueType(name='int', is_volatile=True), - doc='status of the task', - ), - ), - )), ('mjuiState', StructDecl( name='mjuiState', diff --git a/python/mujoco/structs.h b/python/mujoco/structs.h index 62b18431..2c84d814 100644 --- a/python/mujoco/structs.h +++ b/python/mujoco/structs.h @@ -16,6 +16,7 @@ #define MUJOCO_PYTHON_STRUCTS_H_ #include +#include #include #include #include @@ -579,6 +580,7 @@ class MjWrapper: public WrapperBase { py_array_or_tuple_t contact; + py_array_or_tuple_t maxuse_threadstack; py_array_or_tuple_t warning; py_array_or_tuple_t timer; py_array_or_tuple_t solver; diff --git a/src/engine/engine_io.c b/src/engine/engine_io.c index 2a23386e..f8b0c0c1 100644 --- a/src/engine/engine_io.c +++ b/src/engine/engine_io.c @@ -1420,6 +1420,7 @@ static void _resetData(const mjModel* m, mjData* d, unsigned char debug_value) { // clear memory utilization stats d->maxuse_stack = 0; + mju_zeroSizeT(d->maxuse_threadstack, mjMAXTHREADS); d->maxuse_arena = 0; d->maxuse_con = 0; d->maxuse_efc = 0; diff --git a/src/engine/engine_util_misc.c b/src/engine/engine_util_misc.c index 924d0bfc..06361e23 100644 --- a/src/engine/engine_util_misc.c +++ b/src/engine/engine_util_misc.c @@ -1213,6 +1213,10 @@ void mju_zeroInt(int* res, int n) { } +void mju_zeroSizeT(size_t* res, size_t n) { + memset(res, 0, n*sizeof(size_t)); +} + // copy int vector vec into res void mju_copyInt(int* res, const int* vec, int n) { diff --git a/src/engine/engine_util_misc.h b/src/engine/engine_util_misc.h index 08ca64fa..32417f2c 100644 --- a/src/engine/engine_util_misc.h +++ b/src/engine/engine_util_misc.h @@ -122,6 +122,9 @@ MJAPI int mju_isZero(mjtNum* vec, int n); // set integer vector to 0 MJAPI void mju_zeroInt(int* res, int n); +// set size_t vector to 0 +MJAPI void mju_zeroSizeT(size_t* res, size_t n); + // copy int vector vec into res MJAPI void mju_copyInt(int* res, const int* vec, int n); diff --git a/src/thread/thread_pool.cc b/src/thread/thread_pool.cc index 6916849f..1b1723ae 100644 --- a/src/thread/thread_pool.cc +++ b/src/thread/thread_pool.cc @@ -14,6 +14,7 @@ #include "thread/thread_pool.h" +#include #include #include #include @@ -55,7 +56,7 @@ class ThreadPoolImpl : public mjThreadPool { public: ThreadPoolImpl(int num_worker) : mjThreadPool{num_worker} { // initialize worker threads - for (int i = 0; i < num_worker; ++i) { + for (int i = 0; i < std::min(num_worker, mjMAXTHREADS); ++i) { WorkerThread worker{ std::make_unique(ThreadPoolWorker, this)}; workers_.push_back(std::move(worker)); diff --git a/unity/Runtime/Bindings/MjBindings.cs b/unity/Runtime/Bindings/MjBindings.cs index 218c4d87..245de196 100644 --- a/unity/Runtime/Bindings/MjBindings.cs +++ b/unity/Runtime/Bindings/MjBindings.cs @@ -58,6 +58,7 @@ public const bool THIRD_PARTY_MUJOCO_MJRENDER_H_ = true; public const int mjNAUX = 10; public const int mjMAXTEXTURE = 1000; public const bool THIRD_PARTY_MUJOCO_INCLUDE_MJTHREAD_H_ = true; +public const int mjMAXTHREADS = 128; public const bool THIRD_PARTY_MUJOCO_INCLUDE_MJTNUM_H_ = true; public const bool mjUSEDOUBLE = true; public const double mjMINVAL = 1e-15; @@ -580,6 +581,134 @@ public unsafe struct mjData_ { public UIntPtr pbase; public UIntPtr parena; public UIntPtr maxuse_stack; + public UIntPtr maxuse_threadstack0; + public UIntPtr maxuse_threadstack1; + public UIntPtr maxuse_threadstack2; + public UIntPtr maxuse_threadstack3; + public UIntPtr maxuse_threadstack4; + public UIntPtr maxuse_threadstack5; + public UIntPtr maxuse_threadstack6; + public UIntPtr maxuse_threadstack7; + public UIntPtr maxuse_threadstack8; + public UIntPtr maxuse_threadstack9; + public UIntPtr maxuse_threadstack10; + public UIntPtr maxuse_threadstack11; + public UIntPtr maxuse_threadstack12; + public UIntPtr maxuse_threadstack13; + public UIntPtr maxuse_threadstack14; + public UIntPtr maxuse_threadstack15; + public UIntPtr maxuse_threadstack16; + public UIntPtr maxuse_threadstack17; + public UIntPtr maxuse_threadstack18; + public UIntPtr maxuse_threadstack19; + public UIntPtr maxuse_threadstack20; + public UIntPtr maxuse_threadstack21; + public UIntPtr maxuse_threadstack22; + public UIntPtr maxuse_threadstack23; + public UIntPtr maxuse_threadstack24; + public UIntPtr maxuse_threadstack25; + public UIntPtr maxuse_threadstack26; + public UIntPtr maxuse_threadstack27; + public UIntPtr maxuse_threadstack28; + public UIntPtr maxuse_threadstack29; + public UIntPtr maxuse_threadstack30; + public UIntPtr maxuse_threadstack31; + public UIntPtr maxuse_threadstack32; + public UIntPtr maxuse_threadstack33; + public UIntPtr maxuse_threadstack34; + public UIntPtr maxuse_threadstack35; + public UIntPtr maxuse_threadstack36; + public UIntPtr maxuse_threadstack37; + public UIntPtr maxuse_threadstack38; + public UIntPtr maxuse_threadstack39; + public UIntPtr maxuse_threadstack40; + public UIntPtr maxuse_threadstack41; + public UIntPtr maxuse_threadstack42; + public UIntPtr maxuse_threadstack43; + public UIntPtr maxuse_threadstack44; + public UIntPtr maxuse_threadstack45; + public UIntPtr maxuse_threadstack46; + public UIntPtr maxuse_threadstack47; + public UIntPtr maxuse_threadstack48; + public UIntPtr maxuse_threadstack49; + public UIntPtr maxuse_threadstack50; + public UIntPtr maxuse_threadstack51; + public UIntPtr maxuse_threadstack52; + public UIntPtr maxuse_threadstack53; + public UIntPtr maxuse_threadstack54; + public UIntPtr maxuse_threadstack55; + public UIntPtr maxuse_threadstack56; + public UIntPtr maxuse_threadstack57; + public UIntPtr maxuse_threadstack58; + public UIntPtr maxuse_threadstack59; + public UIntPtr maxuse_threadstack60; + public UIntPtr maxuse_threadstack61; + public UIntPtr maxuse_threadstack62; + public UIntPtr maxuse_threadstack63; + public UIntPtr maxuse_threadstack64; + public UIntPtr maxuse_threadstack65; + public UIntPtr maxuse_threadstack66; + public UIntPtr maxuse_threadstack67; + public UIntPtr maxuse_threadstack68; + public UIntPtr maxuse_threadstack69; + public UIntPtr maxuse_threadstack70; + public UIntPtr maxuse_threadstack71; + public UIntPtr maxuse_threadstack72; + public UIntPtr maxuse_threadstack73; + public UIntPtr maxuse_threadstack74; + public UIntPtr maxuse_threadstack75; + public UIntPtr maxuse_threadstack76; + public UIntPtr maxuse_threadstack77; + public UIntPtr maxuse_threadstack78; + public UIntPtr maxuse_threadstack79; + public UIntPtr maxuse_threadstack80; + public UIntPtr maxuse_threadstack81; + public UIntPtr maxuse_threadstack82; + public UIntPtr maxuse_threadstack83; + public UIntPtr maxuse_threadstack84; + public UIntPtr maxuse_threadstack85; + public UIntPtr maxuse_threadstack86; + public UIntPtr maxuse_threadstack87; + public UIntPtr maxuse_threadstack88; + public UIntPtr maxuse_threadstack89; + public UIntPtr maxuse_threadstack90; + public UIntPtr maxuse_threadstack91; + public UIntPtr maxuse_threadstack92; + public UIntPtr maxuse_threadstack93; + public UIntPtr maxuse_threadstack94; + public UIntPtr maxuse_threadstack95; + public UIntPtr maxuse_threadstack96; + public UIntPtr maxuse_threadstack97; + public UIntPtr maxuse_threadstack98; + public UIntPtr maxuse_threadstack99; + public UIntPtr maxuse_threadstack100; + public UIntPtr maxuse_threadstack101; + public UIntPtr maxuse_threadstack102; + public UIntPtr maxuse_threadstack103; + public UIntPtr maxuse_threadstack104; + public UIntPtr maxuse_threadstack105; + public UIntPtr maxuse_threadstack106; + public UIntPtr maxuse_threadstack107; + public UIntPtr maxuse_threadstack108; + public UIntPtr maxuse_threadstack109; + public UIntPtr maxuse_threadstack110; + public UIntPtr maxuse_threadstack111; + public UIntPtr maxuse_threadstack112; + public UIntPtr maxuse_threadstack113; + public UIntPtr maxuse_threadstack114; + public UIntPtr maxuse_threadstack115; + public UIntPtr maxuse_threadstack116; + public UIntPtr maxuse_threadstack117; + public UIntPtr maxuse_threadstack118; + public UIntPtr maxuse_threadstack119; + public UIntPtr maxuse_threadstack120; + public UIntPtr maxuse_threadstack121; + public UIntPtr maxuse_threadstack122; + public UIntPtr maxuse_threadstack123; + public UIntPtr maxuse_threadstack124; + public UIntPtr maxuse_threadstack125; + public UIntPtr maxuse_threadstack126; + public UIntPtr maxuse_threadstack127; public UIntPtr maxuse_arena; public int maxuse_con; public int maxuse_efc;