41. Lighting wrong on stretched mesh
A sphere scaled (2, 1, 1) has wrong lighting in a custom shader that transforms normals with the model matrix. What is the correct normal transform?
- A.The model matrix itself, then skip normalising
- B.The view-projection matrix
- C.The inverse transpose of the model matrix's upper 3x3, then normalise
- D.The transpose of the projection matrix
Show answer
Answer: C. The inverse transpose of the model matrix's upper 3x3, then normalise
Under non-uniform scale, transforming a normal like a position tilts it so it is no longer perpendicular to the surface. The inverse transpose keeps normals perpendicular. For rotation and uniform scale only, the model matrix works, which is why the bug appears only on stretched objects.
42. Why fp16 needs loss scaling but bf16 usually does not
Mixed precision training with fp16 often needs dynamic loss scaling, while bf16 training usually works without it. Why?
- A.bf16 has more mantissa bits than fp32
- B.fp16 does not support matrix multiplication on GPUs
- C.bf16 has the same exponent range as fp32, so small gradients do not underflow to zero
- D.bf16 automatically averages gradients across devices
Show answer
Answer: C. bf16 has the same exponent range as fp32, so small gradients do not underflow to zero
fp16 has only 5 exponent bits, so very small gradient values underflow to zero; loss scaling multiplies the loss to shift gradients into range. bf16 keeps fp32 8 exponent bits (same range) but fewer mantissa bits, so underflow is rare, at the cost of lower precision.
43. Why Adam divides by 1 - beta^t
Adam uses m_hat = m / (1 - beta1^t) and v_hat = v / (1 - beta2^t). Why?
- A.It applies weight decay to the moment estimates
- B.The moments start at zero, so early estimates are biased low
- C.It clips any gradient that is too large
- D.It anneals the learning rate to zero by the end
Show answer
Answer: B. The moments start at zero, so early estimates are biased low
Both moving averages are initialised at zero, so in the first steps they underestimate the true mean and variance of the gradient. Dividing by (1 - beta^t) corrects that bias, and the correction fades as t grows. Without it, v would be tiny early and the first updates could be badly scaled.
44. Gradient shrink through ten sigmoids
The sigmoid derivative is at most 0.25. Ignoring weights, at most what factor can a gradient keep after passing back through 10 sigmoid layers?
- A.About 1 in 40
- B.About 1 in a million
- C.About a quarter
- D.About 1 in a thousand
Show answer
Answer: B. About 1 in a million
0.25¹⁰ = 1 / 4¹⁰ = 1 / 1,048,576, about one millionth. This is the vanishing gradient problem in its simplest form: early layers get almost no learning signal. ReLU-family activations, residual connections and normalisation help.
45. Keys prefixed with module.
load_state_dict fails: missing keys "fc.weight", unexpected keys "module.fc.weight". The checkpoint was saved from a DistributedDataParallel model. What is the fix?
- A.Pass strict=False and ignore the warning
- B.Retrain the whole model without DDP
- C.Strip the "module." prefix from the keys
- D.Load the checkpoint onto the CPU first
Show answer
Answer: C. Strip the "module." prefix from the keys
DDP wraps the model, so its state_dict keys gain a "module." prefix. Saving model.module.state_dict() avoids it, or you can rename keys when loading. strict=False would load nothing useful, leaving random weights.
46. Calling backward twice
You call loss.backward() and then loss.backward() again on the same graph. PyTorch raises "Trying to backward through the graph a second time". Why?
- A.Gradients can only be computed once per model
- B.The optimiser locks the graph
- C.The loss is detached after the first call
- D.The saved tensors are freed after the first backward
Show answer
Answer: D. The saved tensors are freed after the first backward
By default backward() frees the intermediate buffers it used, to save memory. To backpropagate through the same graph again, pass retain_graph=True the first time. Usually the real fix is to run a fresh forward pass.
47. Parameters in a depthwise separable conv
Ignoring biases, a standard 3×3 conv from 64 to 128 channels has 3·3·64·128 = 73,728 weights. How many does a depthwise separable version (3×3 depthwise on 64 channels, then 1×1 to 128) have?
- A.73,728
- B.576
- C.8,768
- D.8,192
Show answer
Answer: C. 8,768
Depthwise: one 3×3 filter per input channel = 9 × 64 = 576. Pointwise: 64 × 128 = 8,192. Total 8,768, about 8.4 times fewer. MobileNet-style models use this to run on phones.
48. An augmentation that changes the label
You train a model to read handwritten digits and add random horizontal and vertical flips. Accuracy on 6 and 9 drops sharply. Why?
- A.Flips make the images too large
- B.Flips turn some digits into others
- C.Flips need a much larger batch size
- D.Flipped images cannot be normalised
Show answer
Answer: B. Flips turn some digits into others
Augmentations must keep the label true. Rotating or flipping a 6 can make it look like a 9 while keeping the label 6, which teaches the model contradictions. Choose transformations that are realistic for the task.
49. Padding in a batch of sentences
Sentences of length 5 to 60 are zero-padded to 60 in one batch. Why use pack_padded_sequence before an LSTM?
- A.So the LSTM skips pads and keeps true final states
- B.So the whole batch fits on a single GPU
- C.So padding tokens get an embedding of their own
- D.So the LSTM can run without any gradients
Show answer
Answer: A. So the LSTM skips pads and keeps true final states
Without packing, a 5-word sentence's final hidden state comes after 55 pad steps, which corrupts it and wastes compute. Packing tells the RNN each sequence's real length, so it stops at the right point.
50. Sharing embedding and output weights
Many language models tie the output projection to the input embedding matrix. What is the main effect?
- A.The model can only output the input tokens
- B.Training becomes non-differentiable
- C.Fewer parameters, often with equal or better quality
- D.The vocabulary must double in size
Show answer
Answer: C. Fewer parameters, often with equal or better quality
Both matrices are vocab × d_model, so sharing them removes one large copy. Using the same vectors to read and write tokens also acts as a useful constraint, and quality usually holds or improves.
51. The reparameterisation trick
In a variational autoencoder, why is z sampled as z = μ + σ·ε with ε ~ N(0, 1) rather than drawn directly from N(μ, σ²)?
- A.So z is always positive
- B.So gradients can flow through μ and σ
- C.So the decoder needs no weights
- D.So the KL term becomes zero
Show answer
Answer: B. So gradients can flow through μ and σ
Sampling directly is not differentiable with respect to μ and σ. Moving the randomness into ε makes z a deterministic function of μ and σ plus independent noise, so backpropagation works.
52. Reach of sliding-window attention
Each layer of a model uses sliding-window attention over the previous 4,096 tokens. Stacking 32 such layers, roughly how far back can information travel to the last position?
- A.Exactly 4,096 tokens
- B.About 8,192 tokens
- C.Unlimited, at no cost
- D.About 131,000 tokens
Show answer
Answer: D. About 131,000 tokens
Each layer lets information move up to one window back, so through L layers the reach is about L × W = 32 × 4,096 ≈ 131,072 tokens. Per-layer cost stays linear in sequence length, but information from far away is passed indirectly and can weaken.
53. Attention to padding tokens
A batch of sentences is padded to the same length, but no padding mask is passed to the encoder's self-attention. What goes wrong?
- A.Tokens attend to pads, so output depends on padding
- B.Pad tokens are dropped from the batch automatically
- C.The model refuses to run with mixed lengths
- D.Only the loss changes, never the outputs
Show answer
Answer: A. Tokens attend to pads, so output depends on padding
Without a key padding mask, pad positions get attention weight like any other token, so the same sentence gives different outputs depending on how much padding its batch has. The mask sets pad scores to −∞ so they get zero weight.
54. Gradient of softmax cross-entropy
Softmax outputs are p = [0.7, 0.2, 0.1] and the true class is index 0. What is the gradient of the cross-entropy loss with respect to the three logits?
- A.[−0.3, 0.2, 0.1]
- B.[0.3, −0.2, −0.1]
- C.[−0.7, 0.2, 0.1]
- D.[0.7, 0.2, 0.1]
Show answer
Answer: A. [−0.3, 0.2, 0.1]
For softmax followed by cross-entropy, ∂L/∂z = p − y, where y is the one-hot target [1, 0, 0]. That gives [0.7 − 1, 0.2, 0.1] = [−0.3, 0.2, 0.1]. This simple form is why the two are fused in one loss.
55. Gradient of a linear layer's weights
A layer computes y = Wx with x of size 3 and y of size 2, so W is 2 × 3. Given the upstream gradient δ = ∂L/∂y (size 2), what is ∂L/∂W?
- A.δ xᵀ, a 2 × 3 matrix
- B.xᵀ δ, a single number
- C.Wᵀ δ, a vector of size 3
- D.x δᵀ, a 3 × 2 matrix
Show answer
Answer: A. δ xᵀ, a 2 × 3 matrix
Each weight W_ij affects y_i through x_j, so ∂L/∂W_ij = δ_i x_j, which is the outer product δxᵀ with the same 2 × 3 shape as W. Wᵀδ is the gradient passed back to x, not to W.
56. Adam and a scaled-up loss
You multiply the loss by 1,000 and keep Adam's learning rate the same. Ignoring eps, what happens to the size of Adam's parameter updates?
- A.1,000 times larger
- B.Roughly unchanged
- C.1,000 times smaller
- D.About 31 times larger
Show answer
Answer: B. Roughly unchanged
Adam divides the gradient's moving average by the square root of the squared-gradient average. Scaling every gradient by c scales both by c, so they cancel. Plain SGD updates would be 1,000 times larger.
57. Test error falls again with more parameters
As model size grows, test error first drops, then rises near the point where the model can just fit the training data, then drops again for much larger models. What is this called?
- A.Double descent
- B.Catastrophic forgetting
- C.Mode collapse
- D.Gradient explosion
Show answer
Answer: A. Double descent
Double descent shows the classic U-shaped bias-variance curve is only part of the story. Around the interpolation threshold, models fit noise badly; much larger models can fit the data in smoother ways and generalise better. It can also appear over training epochs.
58. Writing a custom autograd Function
In a torch.autograd.Function subclass, what must backward(ctx, grad_output) return?
- A.The loss value for the batch
- B.One gradient per forward input, None for non-tensors
- C.The updated parameters
- D.A single scalar summarising all gradients
Show answer
Answer: B. One gradient per forward input, None for non-tensors
backward receives the gradient of the loss with respect to the output and must return the gradient with respect to each input of forward, in order. Inputs that need no gradient, such as ints or flags, get None. Use gradcheck to verify it.
59. Multi-GPU job that hangs forever
A distributed job hangs with no error. Code does `if loss < threshold: dist.all_reduce(metric)`, and loss differs between ranks. What is wrong?
- A.all_reduce cannot sum floating-point values
- B.Some ranks enter the collective and others never do
- C.The threshold must be the same type as loss
- D.NCCL only supports 2 GPUs
Show answer
Answer: B. Some ranks enter the collective and others never do
Collective operations need every rank to call them in the same order. If only some ranks take the branch, they wait forever for the others. Make the decision identical on all ranks (for example, all-reduce the condition first), and set NCCL timeouts and debug logging to catch such hangs.
60. Training past compute-optimal
Llama 3 8B was trained on about 15 trillion tokens, far beyond the ~160B that Chinchilla's rule suggests. Why would a lab do this?
- A.A smaller model trained longer is cheaper to serve at a given quality level
- B.Chinchilla's rule only applies to encoder-only models
- C.Training longer always lowers the total training compute
- D.Extra tokens are needed to fill the tokenizer's vocabulary
Show answer
Answer: A. A smaller model trained longer is cheaper to serve at a given quality level
Chinchilla minimises training compute for a target loss, but it ignores inference. If a model will serve billions of requests, a smaller one trained on many more tokens can match a bigger model's quality while costing far less per token to run. Loss keeps improving slowly well past 20 tokens per parameter.