Parallel factor_m
This commit is contained in:
@@ -228,8 +228,10 @@ def factor_m(m: Model, d: Data) -> Data:
|
|||||||
return d
|
return d
|
||||||
|
|
||||||
# build up indices for where we will do backwards updates over qLD
|
# build up indices for where we will do backwards updates over qLD
|
||||||
# TODO(erikfrey): do fewer updates by combining non-overlapping ranges
|
|
||||||
dof_madr = jp.array(m.dof_Madr)
|
dof_madr = jp.array(m.dof_Madr)
|
||||||
|
depth = []
|
||||||
|
for i in range(m.nv):
|
||||||
|
depth.append(depth[m.dof_parentid[i]] + 1 if m.dof_parentid[i] != -1 else 0)
|
||||||
updates = {}
|
updates = {}
|
||||||
madr_ds = []
|
madr_ds = []
|
||||||
for i in range(m.nv):
|
for i in range(m.nv):
|
||||||
@@ -240,21 +242,31 @@ def factor_m(m: Model, d: Data) -> Data:
|
|||||||
madr_ij, j = madr_ij + 1, m.dof_parentid[j]
|
madr_ij, j = madr_ij + 1, m.dof_parentid[j]
|
||||||
if j == -1:
|
if j == -1:
|
||||||
break
|
break
|
||||||
madr_j_range = tuple(m.dof_Madr[j : j + 2])
|
out_beg, out_end = tuple(m.dof_Madr[j : j + 2])
|
||||||
updates.setdefault(madr_j_range, []).append((madr_d, madr_ij))
|
updates.setdefault(depth[j], []).append((out_beg, out_end, madr_d, madr_ij))
|
||||||
|
|
||||||
qld = d.qM
|
qld = d.qM
|
||||||
|
|
||||||
for (out_beg, out_end), vals in sorted(updates.items(), reverse=True):
|
for _, updates in sorted(updates.items(), reverse=True):
|
||||||
madr_d, madr_ij = jp.array(vals).T
|
# combine the updatess into one update batch (per depth level)
|
||||||
|
rows = []
|
||||||
|
madr_ijs = []
|
||||||
|
pivots = []
|
||||||
|
out = []
|
||||||
|
|
||||||
@jax.vmap
|
for (b, e, madr_d, madr_ij) in updates:
|
||||||
def off_diag_fn(madr_d, madr_ij, qld=qld, width=out_end - out_beg):
|
width = e - b
|
||||||
qld_row = jax.lax.dynamic_slice(qld, (madr_ij,), (width,))
|
rows.append(np.arange(madr_ij, madr_ij + width))
|
||||||
return -(qld_row[0] / qld[madr_d]) * qld_row
|
madr_ijs.append(np.full((width,), madr_ij))
|
||||||
|
pivots.append(np.full((width,), madr_d))
|
||||||
|
out.append(np.arange(b, e))
|
||||||
|
rows = jp.array(np.concatenate(rows))
|
||||||
|
madr_ijs = jp.array(np.concatenate(madr_ijs))
|
||||||
|
pivots = jp.array(np.concatenate(pivots))
|
||||||
|
out = jp.array(np.concatenate(out))
|
||||||
|
|
||||||
qld_update = jp.sum(off_diag_fn(madr_d, madr_ij), axis=0)
|
# apply the update batch
|
||||||
qld = qld.at[out_beg:out_end].add(qld_update)
|
qld = qld.at[out].add(-(qld[madr_ijs] / qld[pivots]) * qld[rows])
|
||||||
# TODO(erikfrey): determine if this minimum value guarding is necessary:
|
# TODO(erikfrey): determine if this minimum value guarding is necessary:
|
||||||
# qld = qld.at[dof_madr].set(jp.maximum(qld[dof_madr], _MJ_MINVAL))
|
# qld = qld.at[dof_madr].set(jp.maximum(qld[dof_madr], _MJ_MINVAL))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user