Tensor Parallelism › Column Parallelism

Michael BrenndoerferJanuary 19, 20267 min read
Language AI HandbookAll chapters
Part 31 of 67Training Infrastructure
Chapter 223Tensor Parallelism › Column Parallelism
Reading section 3 of 12 · Column Parallelism · 7 minSection 3 of 12 · 7 min

Book contents

Section 3 of 12 · 7 min read

Tensor Parallelism › Column ParallelismOne section · Sections in this chapter3 / 12 ↓
Reading tools Definitions & inline links

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

Column parallelism splits a weight matrix along its output (column) dimension. Given NN GPUs with indices 0,1,…,N−10, 1, \ldots, N-1, we partition the weight matrix A∈Rd×hA \in \mathbb{R}^{d \times h} into NN column slices:

A=[A0∣A1∣⋯∣AN−1]A = [A_0 \mid A_1 \mid \cdots \mid A_{N-1}]

where each Ai∈Rd×(h/N)A_i \in \mathbb{R}^{d \times (h/N)}.

Each GPU ii stores its slice AiA_i and computes:

Yi=XAiY_i = X A_i

where:

  • X∈Rb×dX \in \mathbb{R}^{b \times d} is the full input, replicated on all GPUs
  • Ai∈Rd×(h/N)A_i \in \mathbb{R}^{d \times (h/N)} is the column shard on GPU ii
  • Yi∈Rb×(h/N)Y_i \in \mathbb{R}^{b \times (h/N)} is the partial output on GPU ii

The partial outputs YiY_i together form the full output: concatenating [Y0,Y1,…,YN−1][Y_0, Y_1, \ldots, Y_{N-1}] along the column dimension recovers the full Y=XA∈Rb×hY = XA \in \mathbb{R}^{b \times h}. This is correct because matrix multiplication with a partitioned weight matrix produces a partitioned result:

XA=X[A0∣A1∣⋯∣AN−1]=[XA0∣XA1∣⋯∣XAN−1]XA = X[A_0 \mid A_1 \mid \cdots \mid A_{N-1}] = [XA_0 \mid XA_1 \mid \cdots \mid XA_{N-1}]

The critical observation is that each GPU's computation Yi=XAiY_i = XA_i is completely independent. No communication is needed during the forward pass to produce YiY_i; each device can compute its shard without knowledge of what the other devices are doing. The price is that the input XX must be fully available on every GPU before computation begins. In practice, this is handled by an all-gather operation at the start of the layer or by keeping the input in the replicated state (which happens automatically when tensor parallelism is paired with data parallelism).

Why is replicating the input acceptable? Because the input to each transformer layer is the residual stream, which after an all-reduce from the previous layer is identical on all GPUs. There is no communication cost to have a replicated input in steady-state operation, since the previous layer's row-parallel all-reduce already distributed it.

Column Parallelism for Multi-Head Attention

Column parallelism is natural for the query, key, and value projections in multi-head attention. Recall that multi-head attention splits the model's hidden dimension into NhN_h heads, where each head operates on a dk=d/Nhd_k = d / N_h dimensional subspace. When you have NN GPUs and split the weight matrix along the head dimension, each GPU naturally handles Nh/NN_h / N attention heads. The column-parallel split corresponds exactly to distributing heads across devices.

This alignment between tensor parallelism and multi-head attention is not a coincidence. The original Megatron-LM paper was designed with this correspondence in mind. Because attention heads are completely independent of one another during the self-attention computation (they attend to the full sequence in parallel subspaces without interacting), you can assign entire heads to individual GPUs and have each GPU compute attention for its assigned heads without ever communicating with other GPUs during the attention computation itself. The interaction between heads happens only when their outputs are projected back to the model's hidden dimension, and that projection is handled by the row-parallel output projection.

For an attention layer with hidden size d=4096d = 4096 and 32 heads on 4 GPUs, each GPU holds the Q, K, V projection weights for 8 heads: matrices of size 4096×10244096 \times 1024 rather than 4096×40964096 \times 4096. Each GPU attends over its 8 heads independently and produces attention outputs of size b×1024b \times 1024. The output projection then acts on these 1024-dimensional features row-parallel, accumulating the full 4096-dimensional output across GPUs via all-reduce.

Column Parallelism for the Feed-Forward Network

The feed-forward network (FFN) also benefits from column parallelism. A standard transformer FFN applies two linear transformations with a nonlinearity between them:

FFN(X)=σ(XW1+b1)W2+b2\text{FFN}(X) = \sigma(XW_1 + b_1) W_2 + b_2

where:

  • X∈Rb×dX \in \mathbb{R}^{b \times d} is the input batch with bb tokens and hidden dimension dd
  • W1∈Rd×4dW_1 \in \mathbb{R}^{d \times 4d} is the expansion weight matrix, increasing the dimension by a factor of 4
  • b1∈R4db_1 \in \mathbb{R}^{4d} is the expansion bias
  • σ(⋅)\sigma(\cdot) is the activation function (GeLU in most modern transformers, ReLU in older ones)
  • W2∈R4d×dW_2 \in \mathbb{R}^{4d \times d} is the contraction weight matrix, reducing back to dd
  • b2∈Rdb_2 \in \mathbb{R}^{d} is the output bias

Column parallelism applied to W1W_1 splits the expansion across GPUs. GPU ii receives the full input XX and computes XW1,iXW_{1,i} using its column shard W1,i∈Rd×dW_{1,i} \in \mathbb{R}^{d \times d} (for a 4-way split of a 4d4d-dimensional FFN). The activation function is then applied locally because GeLU and ReLU operate element-wise on each dimension independently. This is a subtle but important point: element-wise nonlinearities are trivially parallelizable because each output element depends on exactly one input element, which lies entirely within the local shard.

After the nonlinearity, each GPU holds Z^i=σ(XW1,i)∈Rb×d\hat{Z}_i = \sigma(XW_{1,i}) \in \mathbb{R}^{b \times d}. These shards together form the full intermediate activation Z^=[Z^0∣Z^1∣⋯∣Z^N−1]∈Rb×4d\hat{Z} = [\hat{Z}_0 \mid \hat{Z}_1 \mid \cdots \mid \hat{Z}_{N-1}] \in \mathbb{R}^{b \times 4d}, ready to be consumed by the row-parallel second layer.

Out[3]:
Visualization
Diagram showing weight matrix A split into 4 column shards distributed to 4 GPUs with output shards.
Column-parallel split of a weight matrix across 4 GPUs. The full weight matrix A of shape (d, h) is partitioned into 4 equal column shards, each of shape (d, h/4). Every GPU receives the full input X and computes its output shard independently, with no inter-GPU communication required during the forward pass. The four output shards feed directly into the downstream row-parallel layer.