TensorTonic
Problems
Data-Parallel Step with psum
JAX
Medium

Run one gradient descent step for a linear model with the batch split across 8 devices. Use jax.shard_map so that every device differentiates the loss of its own shard of the batch, and use jax.lax.pmean to average the per-device results.

The model predicts xnW+bx_n W + bxn​W+b for example nnn, where xnx_nxn​ is row nnn of x. The loss is the squared error summed over the K outputs and averaged over all N examples.

L(W,b)=1N∑n=1N∑k=1K((xnW+b)k−yn,k)2L(W, b) = \frac{1}{N} \sum_{n=1}^{N} \sum_{k=1}^{K} \left( (x_n W + b)_k - y_{n,k} \right)^2L(W,b)=N1​n=1∑N​k=1∑K​((xn​W+b)k​−yn,k​)2

Here WWW is w with shape (D, K), bbb is b with shape (K,), x has shape (N, D) and y has shape (N, K). Build a one-axis mesh named data over all 8 devices and split x and y along their first dimension, so each device receives N/8 consecutive examples. Each device evaluates the same loss formula on its own N/8 examples and differentiates it with respect to w and b. Every shard has the same size, so the average of the 8 shard losses equals LLL and the average of the 8 shard gradients equals the gradient of LLL. The step then applies

W←W−lr ∇WL,b←b−lr ∇bL.W \leftarrow W - \text{lr} \, \nabla_W L, \qquad b \leftarrow b - \text{lr} \, \nabla_b L.W←W−lr∇W​L,b←b−lr∇b​L.

Return a dict with three keys. w is the updated float32 JAX array of shape (D, K), b is the updated float32 JAX array of shape (K,), and loss is a float32 JAX array of shape () holding LLL at the weights before the update. w and b are returned replicated on all 8 devices.

Examples

Input: w = [[0.0]], b = [0.0], x = [[1.0],[2.0],[3.0],[4.0],[5.0],[6.0],[7.0],[8.0]], y = [[3.0],[5.0],[7.0],[9.0],[11.0],[13.0],[15.0],[17.0]], lr = 0.01

Output: {"w":[[1.11]],"b":[0.2],"loss":121.0}

Explanation: Every device receives one example, so device d holds x = d + 1 and y = 2d + 3. With zero weights every prediction is 0, so the shard losses are 9, 25, 49, 81, 121, 169, 225 and 289, and their average is 121. The shard gradients with respect to w are -2xy, which average to -111, so the step gives w = 0 + 0.01 times 111 = 1.11. The bias gradients are -2y, which average to -20, so b becomes 0.2.

Input: w = [[0.1],[0.3]], b = [0.0], x = [[0.2,0.1],[0.7,0.8],[0.2,-0.7],[-1.3,-3.2],[-0.9,-0.8],[0.1,0.3],[0.3,-0.3],[-0.4,0.2],[0.1,-0.5],[0.4,0.2],[-0.6,0.5],[0.1,-0.2],[0.5,0.0],[1.0,1.0],[-0.1,0.4],[-0.9,-0.4]], y = [[-0.8],[-0.4],[-0.3],[0.1],[-0.6],[-0.3],[-0.6],[-0.7],[0.1],[-0.2],[-0.4],[-0.4],[-0.7],[0.2],[-0.1],[-0.3]], lr = 0.1

Output: {"w":[[0.072288],[0.239088]],"b":[-0.057],"loss":0.303913}

Input: w = [[0.1,1.0],[-1.3,-0.4]], b = [-0.2,-0.3], x = [[-0.5,0.8],[0.4,-0.4],[-0.9,-0.1],[0.8,0.7],[2.0,0.0],[-0.7,-0.4],[-0.2,-0.4],[-0.9,0.1]], y = [[-0.7,1.1],[0.6,-0.6],[0.1,1.3],[-1.0,-0.2],[0.2,-1.1],[0.0,1.0],[-0.3,0.6],[-0.5,1.0]], lr = 0.05

Output: {"w":[[0.104475,0.8363],[-1.291212,-0.39135]],"b":[-0.195125,-0.22975],"loss":3.745738}

Hint 1

jax.make_mesh((8,), ("data",), axis_types=(AxisType.Auto,)) lets shard_map reshard plain inputs.

Hint 2

jax.shard_map(f, mesh=mesh, in_specs=(P(), P(), P("data"), P("data")), out_specs=...).

Hint 3

jax.lax.pcast((w, b), "data", to="varying") marks shared params as per-device; jax.lax.pmean averages across devices.

Requirements

  • The function is traced with jax.make_jaxpr, and the traced program must contain a shard_map whose body receives x blocks of shape (N/8, D) and reduces values across devices.
  • The shard_map body must not also receive the full x or y, for example by closing over them.
  • The reduction inside the body may use jax.lax.pmean or jax.lax.psum on the data axis, and the update must use the average gradient over the batch, never 8 times that amount.
  • The function is called inside jax.jit with every argument traced, so it must not convert traced values, lr included, to Python numbers or branch on them.

Constraints

  • N is 8, 16, 24 or 32, D is between 1 and 4, and K is between 1 and 3.
  • w, b, x and y are float32 JAX arrays with the shapes given above, and every value is finite.
  • lr arrives as a Python float, and jax.jit traces it as a float32 scalar. Its value is positive and no larger than 0.3.
Try Similar Problems
Tensor-Parallel MLPMediumDevice Mesh and Named ShardingEasyRing All-Reduce with ppermuteHardPad and Mask to Bucket LengthMediumHessian-Vector ProductMediumPer-Example Gradient ClippingMediumStraight-Through Estimator with Custom VJPMediumTraced Learning Rate ScheduleMediumExponential Moving Average with ScanMediumSpectral Norm by Power IterationMediumBatched Attention with vmapMediumPairwise Distances with Nested vmapMedium

Accepts: array

Accepts: array

Accepts: array

Accepts: array

Accepts: number

You must run your code first.
Data-Parallel Step with psum

Data-Parallel Step with psum

JAX
Medium

Run one gradient descent step for a linear model with the batch split across 8 devices. Use jax.shard_map so that every device differentiates the loss of its own shard of the batch, and use jax.lax.pmean to average the per-device results.

The model predicts xnW+bx_n W + bxn​W+b for example nnn, where xnx_nxn​ is row nnn of x. The loss is the squared error summed over the K outputs and averaged over all N examples.

L(W,b)=1N∑n=1N∑k=1K((xnW+b)k−yn,k)2L(W, b) = \frac{1}{N} \sum_{n=1}^{N} \sum_{k=1}^{K} \left( (x_n W + b)_k - y_{n,k} \right)^2L(W,b)=N1​n=1∑N​k=1∑K​((xn​W+b)k​−yn,k​)2

Here WWW is w with shape (D, K), bbb is b with shape (K,), x has shape (N, D) and y has shape (N, K). Build a one-axis mesh named data over all 8 devices and split x and y along their first dimension, so each device receives N/8 consecutive examples. Each device evaluates the same loss formula on its own N/8 examples and differentiates it with respect to w and b. Every shard has the same size, so the average of the 8 shard losses equals LLL and the average of the 8 shard gradients equals the gradient of LLL. The step then applies

W←W−lr ∇WL,b←b−lr ∇bL.W \leftarrow W - \text{lr} \, \nabla_W L, \qquad b \leftarrow b - \text{lr} \, \nabla_b L.W←W−lr∇W​L,b←b−lr∇b​L.

Return a dict with three keys. w is the updated float32 JAX array of shape (D, K), b is the updated float32 JAX array of shape (K,), and loss is a float32 JAX array of shape () holding LLL at the weights before the update. w and b are returned replicated on all 8 devices.

Examples

Input: w = [[0.0]], b = [0.0], x = [[1.0],[2.0],[3.0],[4.0],[5.0],[6.0],[7.0],[8.0]], y = [[3.0],[5.0],[7.0],[9.0],[11.0],[13.0],[15.0],[17.0]], lr = 0.01

Output: {"w":[[1.11]],"b":[0.2],"loss":121.0}

Explanation: Every device receives one example, so device d holds x = d + 1 and y = 2d + 3. With zero weights every prediction is 0, so the shard losses are 9, 25, 49, 81, 121, 169, 225 and 289, and their average is 121. The shard gradients with respect to w are -2xy, which average to -111, so the step gives w = 0 + 0.01 times 111 = 1.11. The bias gradients are -2y, which average to -20, so b becomes 0.2.

Input: w = [[0.1],[0.3]], b = [0.0], x = [[0.2,0.1],[0.7,0.8],[0.2,-0.7],[-1.3,-3.2],[-0.9,-0.8],[0.1,0.3],[0.3,-0.3],[-0.4,0.2],[0.1,-0.5],[0.4,0.2],[-0.6,0.5],[0.1,-0.2],[0.5,0.0],[1.0,1.0],[-0.1,0.4],[-0.9,-0.4]], y = [[-0.8],[-0.4],[-0.3],[0.1],[-0.6],[-0.3],[-0.6],[-0.7],[0.1],[-0.2],[-0.4],[-0.4],[-0.7],[0.2],[-0.1],[-0.3]], lr = 0.1

Output: {"w":[[0.072288],[0.239088]],"b":[-0.057],"loss":0.303913}

Input: w = [[0.1,1.0],[-1.3,-0.4]], b = [-0.2,-0.3], x = [[-0.5,0.8],[0.4,-0.4],[-0.9,-0.1],[0.8,0.7],[2.0,0.0],[-0.7,-0.4],[-0.2,-0.4],[-0.9,0.1]], y = [[-0.7,1.1],[0.6,-0.6],[0.1,1.3],[-1.0,-0.2],[0.2,-1.1],[0.0,1.0],[-0.3,0.6],[-0.5,1.0]], lr = 0.05

Output: {"w":[[0.104475,0.8363],[-1.291212,-0.39135]],"b":[-0.195125,-0.22975],"loss":3.745738}

Hint 1

jax.make_mesh((8,), ("data",), axis_types=(AxisType.Auto,)) lets shard_map reshard plain inputs.

Hint 2

jax.shard_map(f, mesh=mesh, in_specs=(P(), P(), P("data"), P("data")), out_specs=...).

Hint 3

jax.lax.pcast((w, b), "data", to="varying") marks shared params as per-device; jax.lax.pmean averages across devices.

Requirements

  • The function is traced with jax.make_jaxpr, and the traced program must contain a shard_map whose body receives x blocks of shape (N/8, D) and reduces values across devices.
  • The shard_map body must not also receive the full x or y, for example by closing over them.
  • The reduction inside the body may use jax.lax.pmean or jax.lax.psum on the data axis, and the update must use the average gradient over the batch, never 8 times that amount.
  • The function is called inside jax.jit with every argument traced, so it must not convert traced values, lr included, to Python numbers or branch on them.

Constraints

  • N is 8, 16, 24 or 32, D is between 1 and 4, and K is between 1 and 3.
  • w, b, x and y are float32 JAX arrays with the shapes given above, and every value is finite.
  • lr arrives as a Python float, and jax.jit traces it as a float32 scalar. Its value is positive and no larger than 0.3.
Try Similar Problems
Tensor-Parallel MLPMediumDevice Mesh and Named ShardingEasyRing All-Reduce with ppermuteHardPad and Mask to Bucket LengthMediumHessian-Vector ProductMediumPer-Example Gradient ClippingMediumStraight-Through Estimator with Custom VJPMediumTraced Learning Rate ScheduleMediumExponential Moving Average with ScanMediumSpectral Norm by Power IterationMediumBatched Attention with vmapMediumPairwise Distances with Nested vmapMedium

Accepts: array

Accepts: array

Accepts: array

Accepts: array

Accepts: number

You must run your code first.
Problems
Loading...
1 / 1