Where the drift lands
Worth reading first: A factorisation kept past its date · Changing the condition number on purpose · The condition number is an amplifier.
A preconditioner is the expensive object in an iterative solve and the obvious one to keep. Every code that solves a sequence keeps one, every one of them has a rule for when to throw it away, and the rule is almost always the same: rebuild when the matrix has changed by more than some fraction of itself.
Written down, that is a threshold on ‖A_t − A₀‖ / ‖A₀‖. It is a perfectly reasonable-looking quantity — it is relative, it is cheap, and it goes to zero when nothing has happened.
It is also the wrong quantity, and the size of the mistake is the condition number.
The experiment
The preconditioner is the exact Cholesky factorisation of the first matrix, which is not what anybody uses and is exactly what this measurement needs: with it, M⁻¹A₀ is the identity to the last bit and conjugate gradients solves the first member in a single step. So every iteration counted afterwards was bought by the drift and by nothing else.
The drift is then built in the spectrum rather than added and measured afterwards. A₀ is constructed with a known eigendecomposition at a prescribed condition number, and the perturbation is
E = s · Σ v_i v_iᵀ
summed over the forty smallest eigenvalues or the forty largest, with s chosen so that the Frobenius norm of E is the same fraction of ‖A₀‖ in both cases. The two drifts are the same size in the norm the rule is written in, to fourteen digits, and that equality is asserted rather than assumed.
The measurement
| ‖E‖ / ‖A₀‖ | on the small eigenvalues | on the large ones |
|---|---|---|
| 10⁻⁶ | 4 iterations | 2 |
| 10⁻⁵ | 5 | 3 |
| 10⁻⁴ | 10 | 4 |
| 10⁻³ | 19 | 5 |
| 10⁻² | 38 | 9 |
| 10⁻¹ | 55 | 19 |
| 1 | 58 | 38 |
At a relative drift of 10⁻³ — a tenth of a per cent, a number most rules would not even react to — the two runs cost 19 iterations and 5. At 10⁻² they cost 38 and 9. The rule cannot distinguish them, because in the rule’s own quantity they are identical.
Why, which is one line
With M the exact factorisation of A₀ and A_t = A₀ + E,
M⁻¹A_t = I + M⁻¹E
and if E is built from A₀’s own eigenvectors with weight w_i on the ith, the eigenvalues of the preconditioned matrix are exactly
1 + w_i / λ_i .
The drift is divided by the eigenvalue it lands on. A perturbation sitting on λ_min is amplified by 1/λ_min; the same perturbation on λ_max is divided by λ_max; and ‖E‖ is the same number in both cases because a Frobenius norm does not know where in the spectrum its mass is.
So the quantity that predicts the cost is max(1 + w_i/λ_i) over min(1 + w_i/λ_i), and at a relative drift of 10⁻³ it is 4.47 on the small end and 1.0327 on the large one. Both are available before either solve starts, from the construction rather than from an eigensolve of the product.
The predictor orders and over-predicts
The predictor gets the ordering right at every drift measured, which is the finding. What it does not get right is the size, and saying so is the second half of an honest measurement.
The conjugate gradient bound applied to a preconditioned condition number of 3.47·10³ asks for 699 iterations. The run takes 58. The bound over-predicts by a factor of twelve, and the fitted slope of iterations against predicted conditioning is 0.176 rather than the bound’s 0.5.
The reason is the one this collection already has an essay about: a stale preconditioner does not spread the spectrum, it splits it. Half of M⁻¹A_t’s eigenvalues are exactly 1, because the drift was placed on the other half, and a method that minimises a polynomial over the spectrum spends nothing on a cluster it has already annihilated. The condition number is a summary of two numbers and the method is reading the whole distribution.
So: where the drift lands decides the cost, and the standard bound built on the same quantity is loose by an order of magnitude. Both statements are about the same figure and neither is a correction to the other.
The object a real code holds
The exact Cholesky above isolates the phenomenon. Nobody keeps one. What a code keeps is an incomplete factorisation, and it ages differently in a way worth drawing.
The drift is the one this collection already has a field about: the five-point operator’s two directions stop being equally weighted, ε running from 1 down to 0.033 over nineteen members, with the sparsity pattern unchanged — so the incomplete factorisation from the first member stays applicable for the whole run, which is exactly the situation in which it gets kept.
The kept factorisation goes
18 21 24 26 29 32 34 36 37 38 38 38 40 42 44 46 48 50 52
iterations. A factorisation rebuilt at every member goes
18 18 18 18 18 17 17 17 17 16 16 16 15 15 15 15 14 14 13
in the opposite direction. The problem is getting easier — an anisotropic operator is a friendlier problem for a factorisation that knows about the anisotropy — and the kept preconditioner is getting worse at it. The two start at the same 18 by construction and never meet again.
The failure mode nobody sees
The incomplete case is the one worth worrying about in practice, and not because it is worse. It is milder, and that is the problem.
A stale factorisation stops converging — a cliff, an error, something in a log. A stale preconditioner never stops converging. It costs 18 iterations, then 30, then 52, and every member returns a correct answer to the tolerance it was asked for. Nothing in the output says that the run is now taking three times as long as it needs to, because nothing in the run knows what it would have taken with a fresh preconditioner.
That is a class of defect this collection keeps meeting: the symptom is absence. There is no wrong number to find, no assertion to trip, and no gate that could be written on the output of a single member. The only way to see it is to run the comparison, and running the comparison means building the fresh preconditioner, which is the thing being avoided.
Two routes to the same number
The predicted conditioning is computed here from the construction — the weights w_i were chosen, the eigenvalues λ_i are known, and 1 + w_i/λ_i is arithmetic on two lists. That is the cheap route and it is only available because the experiment built the drift on purpose.
It would be worth nothing if it did not agree with the expensive route, so the agreement is the check. Forming M⁻¹A_t explicitly and taking the ratio of its extreme eigenvalues gives the same number, and it must: the two are the same quantity computed from two different objects, one of them never assembled. The collection’s standing habit is that a number arrived at by one route has been wrong every time it has been published, and this is the cheapest available second route.
What the agreement licenses is the sentence in the figure’s badge: the conditioning of the preconditioned matrix is knowable before the solve, from quantities a code that built the preconditioner already has. It is not knowable cheaply for a general drift — nobody has A₀’s eigenvectors — but the experiment is not about what is cheap. It is about which quantity the answer depends on, and the answer depends on that one and not on the norm.
What the rule should be written in
If not ‖E‖/‖A₀‖, then what?
The honest answer from this measurement is ‖A₀⁻¹E‖, or anything that behaves like it: the drift measured in the units the preconditioner works in rather than the units the matrix is written in. That quantity is 4.47 and 0.033 for the two drifts above, which is a factor of 135 between two things the naive rule calls equal.
Estimating it is not free — it is a norm of a product with an inverse, which is the object the condition-estimation essays are about — but it is not expensive either, and this collection already has the machinery: an estimate of ‖A₀⁻¹E‖ costs a handful of solves with a factorisation that is already in memory.
The cheaper answer, and the one the essay on what a rebuild is worth is about, is to stop trying to predict and read the iteration count instead. That has its own failure and the two essays are best read together.
What would have to be true for the norm rule to work
It is worth stating the condition under which the standard rule of thumb is right, because it is not empty and because naming it is more useful than saying the rule is wrong.
A threshold on ‖E‖/‖A₀‖ predicts the cost correctly when the drift is spread evenly over the spectrum — when the perturbation has about as much weight on the small eigenvalues as anywhere else. Then max(1 + w_i/λ_i) is proportional to ‖E‖/λ_min, the condition number enters once as a constant, and a threshold calibrated on one problem transfers to another of similar conditioning.
That is a real situation. A drift that is genuinely random with respect to the operator’s eigenvectors — a perturbation from measurement noise, say, or from a rounding — looks like that, and for it the rule is a reasonable proxy.
What is not like that is any drift with structure, which is most of them: a time step that changes one coefficient, a load that acts on part of a domain, an operator whose anisotropy grows. Those have their weight somewhere in particular, and where they have it is exactly the question the norm discards. So the rule is not a bad approximation to the right quantity; it is the right quantity multiplied by an unknown that runs from 1 to the condition number, and nothing in the norm says which.
The refusal
The claim under test is that a relative drift threshold is a usable rule. It is fed the case where it happens to be right, and the case is chosen to be one where being right means nothing.
At a relative drift of 10⁻⁶, the small end costs 4 iterations and the large end costs 2. The assertion that the small end costs more than two and a half times the large one is fed those numbers and fails — correctly, because at that drift neither placement costs anything worth measuring and there is no distinction to make. The threshold rule is right there, in the sense that it makes no error; it is right the way a rule that always says “do nothing” is right on a problem where nothing needs doing.
That is what the refusal is for: to stop the main measurement from being read as a claim that the norm is always wrong. It is wrong where the answer matters and correct where it does not, which is the least useful pattern a rule can have.
One more thing the norm cannot see
There is a second quantity hiding in the incomplete-factorisation figure, and it is worth naming because it is the same mistake in a different disguise.
The drift there is an anisotropy: the operator’s two directions stop being equally weighted. In the Frobenius norm that is a large change — by the last member the matrix is a substantial distance from the first — and a norm-based rule would have rebuilt many members earlier. It would have been right to, but not for the reason it thought: the rule would have fired because the matrix moved, and the correct reason to fire is that the smoothing directions the incomplete factorisation encodes have stopped being the directions the operator is stiff in.
This collection has a whole field about that distinction. Line relaxation along the strong direction and coarsening only along it are both statements about where in the problem the difficulty is, and neither of them is a statement about how far the matrix has moved. A preconditioner is a claim about the structure of the difficulty, and it goes stale when the structure moves rather than when the entries do.
Shares its objects with
Essays that name at least two of the same things, and that neither author linked.
- What a rebuild is worth — both name cholesky factorisation, condition number, conjugate gradients, flop count, incomplete factorisation, preconditioning
- The problem that arrives again — both name cholesky factorisation, condition number, flop count, preconditioning
- A preconditioner that changes sign — both name condition number, conjugate gradients, preconditioning
- The rate the condition number predicts — both name condition number, conjugate gradients, preconditioning
- Two dimensions, and the cluster that thins — both name condition number, conjugate gradients, preconditioning
- A correction cheaper than the problem — both name condition number, flop count
Named objects
A flat tag is an object no other essay names yet.
AnisotropyCholesky factorisationCondition numberConjugate gradientsEigenvalueFlop countIncomplete factorisationPreconditioningSpectral clustering