← Google Interview Insights

Google·Machine Learning Engineer·Onsite - Coding / Algorithms·Senior

Senior
Jul 2026

Summary

Google ML Engineer interview, technical round focused entirely on implementing a Transformer block from scratch. Pretty deep dive, they wanted working code plus a real understanding of the math behind it.

Questions Asked (4)

Q1

Implement a multi-head self-attention module in Python (NumPy or PyTorch), taking an input of shape (batch_size, sequence_length, hidden_dim), splitting into multiple heads, computing scaled dot-product attention with optional masking, and projecting the concatenated output.

System DesignAlgorithms & Data StructuresTechnical Trade-offs
Author's notes

The shape tracking is where things get slippery.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the requirements: input shape, number of heads, masking, and whether to use NumPy or PyTorch. Then outline the steps: linear projections, reshaping for multi-head, scaled dot-product attention with optional mask, concatenation, and final projection. Implement efficiently with vectorized operations, and discuss trade-offs like memory vs. speed.

Pro tip: Mention that you would use `torch.nn.Linear` for projections and `torch.matmul` for batched matrix multiplication, and that you'd verify the implementation against a reference like `torch.nn.MultiheadAttention` to ensure correctness.

1. Clarify requirements and set up

Confirm input dimensions, number of heads, masking type (e.g., padding or causal), and framework. Initialize weight matrices for Q, K, V, and output projections.

2. Linear projections and reshaping

Apply linear layers to input to get Q, K, V. Reshape from (batch, seq_len, hidden_dim) to (batch, num_heads, seq_len, head_dim) by splitting hidden_dim into num_heads * head_dim.

3. Scaled dot-product attention

Compute attention scores as Q @ K^T / sqrt(head_dim). Apply optional mask (e.g., set masked positions to -inf before softmax). Compute softmax and multiply by V.

4. Concatenate and project output

Reshape attention output back to (batch, seq_len, hidden_dim) by concatenating heads, then apply final linear projection.

5. Validate and discuss trade-offs

Test with a small example, compare with a reference implementation, and discuss computational complexity, memory usage, and potential optimizations.

Key Points to Mention

  • Scaling factor 1/sqrt(head_dim) to prevent softmax saturation
  • Masking: additive mask with -inf for padding or causal attention
  • Efficient reshaping using view/transpose/contiguous in PyTorch
  • Batch matrix multiplication (torch.bmm or torch.matmul) for parallel heads
  • Output projection after concatenation to mix information across heads
  • Complexity: O(seq_len^2 * head_dim) per head, memory O(batch * heads * seq_len^2)

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q2

Implement a SwiGLU feed-forward layer where the gate and value projections run in parallel, apply Swish activation to the gate path, multiply elementwise, then project the result.

Technical Trade-offsAlgorithms & Data Structures
Author's notes

I actually liked this part.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the SwiGLU architecture and the parallel gate/value projections, then outline the forward pass step-by-step, emphasizing the elementwise multiplication after Swish activation. Discuss implementation details like matrix shapes, activation function, and potential optimizations, and finally mention trade-offs and use cases.

Pro tip: Highlight that SwiGLU often uses a smaller hidden dimension (e.g., 2/3 of the standard 4x) to keep parameter count comparable, and mention that the parallel projections can be fused into a single matrix multiplication for efficiency.

1. Clarify the architecture

Explain that SwiGLU consists of two parallel linear projections (gate and value) from the input, followed by Swish activation on the gate, elementwise multiplication, and a final output projection.

2. Define the forward pass

Describe the computation: given input x, compute gate = Swish(xW_g + b_g) and value = xW_v + b_v, then multiply elementwise, and finally project with W_o + b_o.

3. Discuss implementation details

Mention matrix dimensions, initialization, and how to implement Swish (x * sigmoid(beta * x), often beta=1). Note that the two projections can be combined into one matrix multiplication for efficiency.

4. Address trade-offs and optimizations

Talk about parameter count, computational cost, and how SwiGLU compares to ReLU/GELU. Mention that the hidden dimension is often reduced (e.g., 2/3 of 4d) to maintain similar parameter count.

5. Provide code or pseudocode

If appropriate, sketch a concise PyTorch implementation to demonstrate clarity and correctness.

Key Points to Mention

  • Swish activation function: x * sigmoid(x) (or with beta parameter)
  • Parallel gate and value projections: can be fused into a single matrix multiplication
  • Elementwise multiplication of activated gate and value
  • Final output projection to original dimension
  • Parameter count and hidden dimension scaling (often 2/3 of 4d)
  • Comparison to other activations (ReLU, GELU) and empirical performance

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q3

Put the attention and feed-forward components together into a full Transformer block with residual connections and layer normalization, returning output with the same shape as the input.

System DesignTechnical Trade-offs
Author's notes

Straightforward once the pieces exist.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by outlining the Transformer block architecture: multi-head attention followed by feed-forward network, each wrapped with residual connections and layer normalization. Then, discuss the order of operations (pre-norm vs post-norm) and how to ensure the output shape matches the input. Finally, mention any implementation details like dropout and activation functions.

Pro tip: Emphasize that pre-norm (LayerNorm before sublayer) is more stable for training deep Transformers, but post-norm (original) can work with careful initialization. Also, note that the residual connection requires the sublayer output to have the same dimension as the input, which is typically ensured by projecting to the model dimension.

1. Define the sublayers

Describe the multi-head attention and feed-forward network sublayers, including their internal operations and output dimensions.

2. Add residual connections

Explain how to add the input of each sublayer to its output, ensuring shapes match, and discuss why this helps with gradient flow.

3. Apply layer normalization

Specify where to apply layer normalization (pre-norm or post-norm) and how it normalizes across the feature dimension.

4. Combine into a block

Show the full forward pass: input -> (LayerNorm -> Attention -> Dropout -> Residual) -> (LayerNorm -> FFN -> Dropout -> Residual) -> output, or the post-norm variant.

5. Verify output shape

Confirm that the output shape equals the input shape, typically (batch_size, sequence_length, model_dim), and mention any necessary projections.

Key Points to Mention

  • Multi-head attention mechanism and its role in capturing dependencies
  • Feed-forward network with two linear layers and a non-linear activation (e.g., ReLU or GELU)
  • Residual connections to mitigate vanishing gradients and enable deep networks
  • Layer normalization for stabilizing training and reducing internal covariate shift
  • Pre-norm vs post-norm architectures and their trade-offs
  • Dropout for regularization and its placement in the block

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q4

Explain the time and memory complexity of multi-head attention, and walk through how masking works across the attention heads.

Technical Trade-offsAlgorithms & Data Structures
Author's notes

Blanked for a second on the memory side.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by defining the notation and then derive the time and memory complexity for multi-head attention, breaking it down into per-head and aggregated costs. Then explain masking as a per-head operation that applies the same mask to each head's attention scores before softmax, and discuss how it affects complexity. Finally, connect the concepts to practical implications like scalability and implementation.

Pro tip: Emphasize that masking does not change the asymptotic complexity but is crucial for correctness in autoregressive and padded scenarios. Mention that efficient implementations often fuse masking with softmax to avoid extra memory overhead.

1. Define notation and setup

Clearly state the dimensions: sequence length n, model dimension d, number of heads h, and per-head dimension d_k = d/h. Assume input and output dimensions are d.

2. Derive time complexity

Compute the cost of linear projections (O(n d^2)), attention scores (O(n^2 d)), and output projection (O(n d^2)). Sum and simplify to O(n^2 d + n d^2).

3. Derive memory complexity

Account for storing inputs, outputs, and intermediate attention matrices. The dominant term is O(n^2 h) for attention scores per head, which simplifies to O(n^2 d) when aggregated.

4. Explain masking mechanism

Describe how masks (e.g., causal or padding) are applied to the attention scores before softmax, independently for each head. The same mask is broadcast across heads.

5. Discuss impact and trade-offs

Note that masking does not alter asymptotic complexity but adds a constant factor. Mention that memory can be reduced by not materializing the full attention matrix if using efficient kernels.

Key Points to Mention

  • Time complexity: O(n^2 d + n d^2) where n is sequence length and d is model dimension.
  • Memory complexity: O(n^2 d) due to attention matrices, but can be optimized.
  • Per-head computation: each head operates on d_k = d/h dimensions, so total cost remains O(n^2 d).
  • Masking is applied per head before softmax, using the same mask across all heads.
  • Masking does not change asymptotic complexity but is essential for autoregressive and padded sequences.
  • Practical optimizations: fused kernels, memory-efficient attention (e.g., FlashAttention) reduce memory overhead.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.