Enable multithreading of Newton solver.

PiperOrigin-RevId: 760723081
Change-Id: Ib7d3c9cec2fdf7dd0e46a570f37c0a6fc5424c7b
This commit is contained in:
Yuval Tassa
2025-05-19 12:17:22 -07:00
committed by Copybara-Service
parent 7edbdd0ad6
commit 94803d772c
+25 -23
View File
@@ -659,32 +659,35 @@ struct mjSolIslandArgs_ {
};
typedef struct mjSolIslandArgs_ mjSolIslandArgs;
// extract arguments, pass to solver
void* mj_solCG_island_wrapper(void* args) {
// extract arguments, pass to CG solver
static void* CG_wrapper(void* args) {
mjSolIslandArgs* solargs = (mjSolIslandArgs*) args;
mj_solCG_island(solargs->m, solargs->d, solargs->island, solargs->m->opt.iterations);
return NULL;
}
// extract arguments, pass to Newton solver
static void* Newton_wrapper(void* args) {
mjSolIslandArgs* solargs = (mjSolIslandArgs*) args;
mj_solNewton_island(solargs->m, solargs->d, solargs->island, solargs->m->opt.iterations);
return NULL;
}
// CG solver, multi-threaded over islands
void mj_solCG_island_multithreaded(const mjModel* m, mjData* d) {
static void solve_threaded(const mjModel* m, mjData* d, int flg_Newton) {
mj_markStack(d);
// allocate array of arguments to be passed to threads
mjSolIslandArgs* sol_cg_island_args = mjSTACKALLOC(d, d->nisland, mjSolIslandArgs);
mjSolIslandArgs* sol_island_args = mjSTACKALLOC(d, d->nisland, mjSolIslandArgs);
mjTask* tasks = mjSTACKALLOC(d, d->nisland, mjTask);
for (int island = 0; island < d->nisland; ++island) {
sol_cg_island_args[island].m = m;
sol_cg_island_args[island].d = d;
sol_cg_island_args[island].island = island;
sol_island_args[island].m = m;
sol_island_args[island].d = d;
sol_island_args[island].island = island;
mju_defaultTask(&tasks[island]);
tasks[island].func = mj_solCG_island_wrapper;
tasks[island].args = &sol_cg_island_args[island];
tasks[island].func = flg_Newton ? Newton_wrapper : CG_wrapper;
tasks[island].args = &sol_island_args[island];
mju_threadPoolEnqueue((mjThreadPool*)d->threadpool, &tasks[island]);
}
@@ -740,23 +743,22 @@ void mj_fwdConstraint(const mjModel* m, mjData* d) {
mju_gather(d->iefc_force, d->efc_force, d->map_iefc2efc, nefc);
mju_gather(d->iefc_aref, d->efc_aref, d->map_iefc2efc, nefc);
// solve per island
if (m->opt.solver == mjSOL_CG) {
if (!d->threadpool) {
// no threadpool, loop over islands
for (int island=0; island < nisland; island++) {
// solve per island, with or without threads
if (!d->threadpool) {
// no threadpool, loop over islands
for (int island=0; island < nisland; island++) {
if (m->opt.solver == mjSOL_NEWTON) {
mj_solNewton_island(m, d, island, m->opt.iterations);
} else {
mj_solCG_island(m, d, island, m->opt.iterations);
}
} else {
// have threadpool, solve using threads
mj_solCG_island_multithreaded(m, d);
}
} else {
for (int island=0; island < nisland; island++) {
mj_solNewton_island(m, d, island, m->opt.iterations);
}
// have threadpool, solve using threads
solve_threaded(m, d, m->opt.solver == mjSOL_NEWTON);
}
// copy back solver outputs (scatter dofs since ni <= nv)
mju_scatter(d->qacc, d->iacc, d->map_idof2dof, nidof);
mju_scatter(d->qfrc_constraint, d->ifrc_constraint, d->map_idof2dof, nidof);