When the algorithm is a table

The order that has a depth

One hundred cells, filled in three orders, producing one table. Row order takes ninety-one steps and anti-diagonal order takes nineteen. Nineteen is not a property of the order — it is the longest chain of cells in the recurrence itself, no schedule can get under it, and every count taken until now was a total that could not see it.

The same table, filled two ways established that a recurrence says what a cell depends on and does not say when to compute it, that at least three orders satisfy the dependencies, and that all three produce a table agreeing cell for cell. It ended with a sentence it could not measure: that a bottom-up fill in anti-diagonal order can be run in parallel and a top-down one cannot.

Every count on this site is a total. Comparisons, swaps, cells, transfers, random bits — each is a sum over everything the algorithm did, and a sum is silent about what had to wait for what. A table is the one place where the missing quantity is exact, needs no model of a machine, and is the same integer on every computer that has ever run the computation.

The same table filled in diagonal order: 100 cellsThe same 100 cells as the plate above, shaded by when they were filled rather than by what they hold. The recurrence says only what a cell depends on; it does not say when to compute it, and diagonal order is one of at least three that work. Every one of them produces a table agreeing cell for cell, which is asserted in the gate rather than assumed.executionintention0136101521283645247111622293746555812172330384756649131824313948576572141925324049586673792026334150596774808527344251606875818690354352616976828791944453627077838892959754637178848993969899one unit = one subproblem given a value100 cells, filled in diagonal order
Fig. 1 The hundred cells of a small edit-distance table, shaded by when each one was filled rather than by what it holds. Under anti-diagonal order every cell on a diagonal depends only on the two diagonals before it, so all the cells of one diagonal can be computed at once — the picture is nineteen bands of colour rather than a hundred. The same hundred cells in row order take ninety-one steps, and the answer in the corner is five either way.

It is exact because a table’s dependencies are written down. Nothing has to be inferred about which operations could overlap: cell (i,j)(i,j) reads three named cells, those three read three each, and the whole structure is a directed acyclic graph that the recurrence spells out. The quantity this page adds is the longest path in that graph, and the reason it can be added now rather than earlier is that it is the first place in this collection where the dependency structure is a datum rather than a guess.

Three numbers where there was one

The quantities separate cleanly and each deserves its own name.

The cells are what this field has counted since its first plate: how many subproblems were given a value. It is a property of the recurrence and the input, and no fill order changes it.

The span is the length of the longest chain of cells, each depending on the one before. For edit distance it is exactly n+m+1n + m + 1: cell (i,j)(i, j) depends on cells whose index sum is smaller, so the sum increases by at least one along any chain, and a chain from (0,0)(0,0) to (n,m)(n,m) can increase it by exactly one each step. It is a property of the recurrence alone. No schedule can finish in fewer rounds than this, whatever hardware is available, and it is computable by looking at the arrows.

The steps are what a given order achieves: how many rounds the fill takes when cells the order has already placed together are allowed to run together. It sits between the span and the cells, and it is the only one of the three that the order controls.

The gap between the cells and the span is the parallelism the recurrence contains. The gap between the span and the steps is how much of it an order throws away.

It is worth checking the definition against the null case, because a measure that reported something interesting about a computation with no parallelism in it would be measuring itself. An insertion sort’s dependency chain runs through every element it moves; a binary search’s runs through every probe; both have a span equal to their work, and both should. Here row order’s span-per-order is 91 against 100 cells, which is nearly equal and not exactly — the small gap is real and is explained two plates below — and anti-diagonal order’s is 19 against 100. A measure that gave 100 and 19 would have been suspiciously tidy.

Cells, steps and the longest chain, against the length of the stringscells filled at a measured slope of 1.96; row order, steps at a measured slope of 1.98; diagonal order, steps at a measured slope of 0.99. The same table filled three ways. Cells rise as the square of the length; the anti-diagonal order's steps rise as the length, because it is the dependency graph's own longest chain; and row order sits with the cells, because a row is itself a chain.10010010³10⁴length of each stringsteps the order takescells filled · 1.96row order, steps · 1.98diagonal order, steps · 0.99one unit = one subproblem given a valuesteps the order takes, n from 16 to 256
Fig. 2 The three quantities across a range of sizes, on the same logarithmic axes every growth claim here is fitted on. The cells rise with a slope of two — the rectangle. The anti-diagonal order’s steps rise with a slope of one, and lie exactly on the recurrence’s own longest chain. Row order’s steps lie on the cells. Two of these three lines are the same line, which is the plate’s whole argument: one order realises all of the available parallelism and the other realises none.

Why row order is sequential and diagonal order is not

The reason is one dependency arrow and it is easy to lose.

Cell (i,j)(i, j) reads (i1,j1)(i-1, j-1), (i1,j)(i-1, j) and (i,j1)(i, j-1). Two of those are in the row above. The third is the cell immediately to the left, in the same row. So a row is not a set of independent cells; it is a chain of them, and filling a row is mm sequential steps however many processors are watching.

Anti-diagonal order groups cells by i+ji + j. Every dependency of a cell on diagonal dd has index sum d1d-1 or d2d-2, and no cell on diagonal dd depends on another cell on diagonal dd — because two cells with the same index sum cannot be one step apart in the required direction. So a diagonal is genuinely a set, all of it can go at once, and there are n+m+1n + m + 1 diagonals.

Column order is the transpose of row order and behaves identically: ninety-one steps on the same hundred cells, for the same reason with the arrow rotated.

order cells steps span widest round
row 100 91 19 2
column 100 91 19 2
anti-diagonal 100 19 19 10

The last column is the one that says what the parallelism is worth: under anti-diagonal order the widest round holds ten cells, so ten workers can be busy at the peak and rather fewer at the ends. The average is a hundred cells over nineteen rounds, about five.

The general rule those three orders are instances of is worth extracting, because it is what carries to other recurrences. An order permits a round exactly where it groups cells that are mutually independent. Row order groups by ii, and cells sharing an ii are chained by the left-neighbour arrow. Anti-diagonal order groups by i+ji+j, and cells sharing i+ji+j have no arrow between them. So the question for any recurrence is which linear function of the indices its arrows all increase, and the level sets of that function are the rounds. For edit distance that function is i+ji+j; for a recurrence whose arrows reached two rows back it would still be i+ji+j but the rounds would be two diagonals apart; for a recurrence with an arrow inside a diagonal there would be no such function and no parallel schedule at all.

The same table filled in row order: 100 cellsThe same 100 cells as the plate above, shaded by when they were filled rather than by what they hold. The recurrence says only what a cell depends on; it does not say when to compute it, and row order is one of at least three that work. Every one of them produces a table agreeing cell for cell, which is asserted in the gate rather than assumed.executionintention0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899one unit = one subproblem given a value100 cells, filled in row order
Fig. 3 The same table in row order, shaded by step. Every cell has its own shade, which is the picture of a computation with no two things happening at once — and it is worth noticing that the shading is nearly a gradient rather than exactly one: the first cell of each row can share a round with the last cell of the row above, since neither depends on the other, which is why the count is ninety-one rather than a hundred.

What the three numbers say about three familiar algorithms

The measure is worth taking outside this table for a moment, because its value is in the comparisons it makes possible and a single computation cannot show them.

A scan — summing an array, finding a maximum — has work nn and span 1 if the combining operation is associative, because the elements can be added in any grouping. That is the extreme case: all of the work is available at once, and a tree of additions finishes in logn\log n rounds with nn workers.

A binary search has work logn\log n and span logn\log n. Every probe’s address is computed from the previous probe’s outcome, so the chain is the whole computation and there is no parallelism at any width. It is the opposite extreme, and it is the reason a search is a poor fit for a machine with many workers however cheap each probe is.

A merge sort has work nlognn \log n and a span dominated by the final merge, which is sequential in the standard implementation and nn long. Its ratio is therefore about logn\log n — genuinely parallel, and far less so than the n/2n/2 this table offers, which is the sort of comparison the two numbers exist to make.

Placing an edit-distance table beside those three puts it near the useful end: work nmnm, span n+mn+m, ratio about n/2n/2. What makes it worth measuring rather than asserting is that the ratio depends on the shape of the table as well as its size — a long string against a short one has span dominated by the long one and work by the product, so a pattern of twenty characters against a text of a million has a ratio of about twenty rather than of half a million. The parallelism available is a property of the inputs’ proportions, and no statement of the algorithm’s class mentions them.

What the span is a bound on, and what it is not

The span is a lower bound on rounds, and it is worth being exact about what a round is, because the temptation to read it as time is strong and wrong.

A round here is one layer of the dependency graph: a set of cells, none of which needs anything another member of the set produces. Saying the computation takes nineteen rounds says that nineteen layers must happen in order. It does not say that a machine with ten processors finishes in nineteen units of anything, because a round’s cells have to be distributed, the results have to be visible to the next round, and both of those cost something this counter does not model.

What the pair of numbers does support is a ratio. Work over span — 100/19 here, and nm/(n+m)nm/(n+m) in general, which is about n/2n/2 on a square table — is the maximum number of workers that could be usefully employed, and it is a property of the problem. On two strings of a thousand characters the ratio is about five hundred, so a machine with five hundred workers could in principle be kept busy and one with five thousand could not. That is a real and useful statement, it is exact, and it required no clock.

It is also the honest limit of the measurement, and this field’s version of the standing caution: the count is not the time, and a round is no more a duration than a comparison or a block transfer is.

Cells, steps and the longest chain, against the length of the stringsrow order, steps at a measured slope of 1.98; diagonal order, steps at a measured slope of 0.99; longest chain at a measured slope of 0.99. The same table filled three ways. Cells rise as the square of the length; the anti-diagonal order's steps rise as the length, because it is the dependency graph's own longest chain; and row order sits with the cells, because a row is itself a chain.10010010³10⁴length of each stringsteps the order takesrow order, steps · 1.98diagonal order, steps · 0.99longest chain · 0.99one unit = one subproblem given a valuesteps the order takes, n from 16 to 256
Fig. 4 The two orders’ step counts against the recurrence’s own longest chain, with the cells left off so the lower two lines can be told apart. They cannot: the anti-diagonal order’s steps and the span are the same numbers at every size, 33 and 33 at sixteen characters and 513 and 513 at two hundred and fifty-six. An order that achieves the span is an optimal schedule, and this one achieves it without being designed to.

There is a second use for the pair that has nothing to do with parallel machines, and it is the one a sequential programmer should care about. The span is also the length of the longest chain of dependent memory reads, and a dependent read is the one thing a modern processor cannot hide: it can execute out of order, issue several loads at once and predict branches, but it cannot fetch a value whose address it does not yet have. So the ratio of work to span is, roughly, how much instruction-level parallelism the computation offers a single core — and the anti-diagonal fill offers a great deal more of it than the row fill, on one processor, with no threads involved. That effect is real, it is what makes vectorised alignment implementations diagonal rather than row-major, and it is invisible in every count on this site including this one.

The order was already load-bearing, and now it carries a third thing

This is the third distinct property the choice of fill order has turned out to decide, and setting the three beside each other is the point of this rung.

The order decides what can be released. The table nobody has to keep showed that row order permits a two-row frontier, column order permits two columns, and anti-diagonal order permits three diagonals — which on a square table is the smallest of the three. The space an algorithm needs is a property of a decision the recurrence does not record.

The order decides what can be skipped. A top-down recursion computes only the cells some later cell will ask for, which on a knapsack is a small fraction of the table; a bottom-up fill computes them all because it has no way to know. That is a property of the same decision, seen from the other side.

And the order decides the depth. Which is this page, and which is the one that costs nothing to have. Row order and anti-diagonal order compute the same cells with the same dependencies; anti-diagonal order takes a fifth of the rounds.

Three properties, one decision, and the decision appears nowhere in a statement of the recurrence. A recurrence is a specification and an order is an implementation, and the collection has now measured three separate consequences of confusing them.

There is a fourth that this field has met without naming it as one. A band as wide as the answer computes a strip of anti-diagonals, and the reason a band is walkable at all is that the band is a set of consecutive diagonals in this ordering — so the technique that prunes the table by a bound is expressed in the coordinate system this page is about, and could not be expressed in row order without care. The order was doing work there too, silently, three rungs before anybody measured it.

The same table filled in column order: 144 cellsThe same 144 cells as the plate above, shaded by when they were filled rather than by what they hold. The recurrence says only what a cell depends on; it does not say when to compute it, and column order is one of at least three that work. Every one of them produces a table agreeing cell for cell, which is asserted in the gate rather than assumed.abrocadabroabracadabra0122436486072849610812013211325374961738597109121133214263850627486981101221343152739516375879911112313541628405264768810011212413651729415365778910111312513761830425466789010211412613871931435567799110311512713982032445668809210411612814092133455769819310511712914110223446587082941061181301421123354759718395107119131143one unit = one subproblem given a value144 cells, filled in column order
Fig. 5 Column order on a different pair — abracadabra against abrocadabro, a hundred and forty-four cells at a distance of two. The transpose of row order and identical in every count, which is the null result this plate exists to record: the two orders that look different on the page are the same schedule with the axes swapped, and the one that looks like a variation is the one that is not.
The same table filled in diagonal order: 100 cellsThe same 100 cells as the plate above, shaded by when they were filled rather than by what they hold. The recurrence says only what a cell depends on; it does not say when to compute it, and diagonal order is one of at least three that work. Every one of them produces a table agreeing cell for cell, which is asserted in the gate rather than assumed.gactacgatgattacagt0136101521283645247111622293746555812172330384756649131824313948576572141925324049586673792026334150596774808527344251606875818690354352616976828791944453627077838892959754637178848993969899one unit = one subproblem given a value100 cells, filled in diagonal order
Fig. 6 The wavefront on a nucleotide pair, where the diagonals are longer relative to the table and the bands are easier to count. Nine characters each way: a hundred cells again, nineteen rounds again, and a widest round of ten again — because none of those three numbers depends on what the characters are. The table’s contents depend entirely on the strings; its schedule does not depend on them at all, which is what makes the depth a property of the recurrence rather than of the input.

Why a top-down fill has no useful depth at all

A memoised recursion computes the same cells and cannot be laid out in layers, and the reason is structural rather than incidental.

The recursion’s control flow is its dependency order: it asks for a subproblem, waits, asks for the next. A schedule that ran two of its calls at once would have to know in advance that neither needs the other’s answer, and knowing that is exactly the analysis a bottom-up fill has already done by choosing an order. So the top-down version’s step count is its call count, its span is the recursion depth, and the two are separated by the branching factor rather than by anything about the table’s shape.

That is the same trade the same table, filled two ways already measured in another unit — a top-down fill asks the table half a million questions and recurses four hundred frames deep — and the depth measurement puts a third column beside those two. The strategy that skips unreachable cells is the one that cannot be laid out in rounds, and the strategy that computes everything is the one that can. Neither dominates, which is the position that essay reached from the space side and this page reaches from the depth side.

Edit distance between intention and execution: 5Each cell holds the distance between a prefix of intention and a prefix of execution. The shaded run from the top left to the bottom right is one optimal alignment; where the table has ties there are others, and this one breaks them towards the diagonal. 100 cells, 100 held at once.executionintention0123456789112345667822234567773333455678434345667854444567776555555678766666656787777776569888888765one unit = one subproblem given a value100 cells, 100 held at once
Fig. 7 The same table with its values rather than its schedule, and the path an optimal alignment takes through it. Every plate above fills exactly these cells and arrives at exactly this five. The schedule is invisible in the result, which is why it took three separate essays to notice that the schedule decides the space, the reachable cells and the depth — none of those is visible in anything the computation returns.

What this does not measure

Three things, and the first is the one that would change an implementation’s behaviour.

Nothing here is charged for communication. Nor for the memory the schedule needs: the frontier a rolling fill can keep is defined by the order, and the table nobody has to keep measured three diagonals for the anti-diagonal order against two rows for row order — so the order with the best depth is not the order with the best space on every table shape, and the two have to be traded rather than optimised separately. A round’s worth of cells has to be given to workers and its results made visible to the next round, and on any real parallel machine that cost is the whole difficulty. The measurement here is of an idealised schedule with free coordination, which makes it a bound rather than a prediction — the same status every floor on this site has.

The band is not swept. A banded fill computes a strip of cells rather than a rectangle, so its cell count falls to O(nk)O(nk) while its span stays at n+m+1n+m+1, and the ratio between them collapses. Cutting the work does not cut the depth, so a banded computation has less parallelism available than a full one, which is a genuine and slightly perverse consequence: the cheaper algorithm is the harder one to spread out. That is measurable with what is already here and is not on any plate.

The rounds are counted, and their contents are not. Nineteen rounds of unequal width is not the same computation as nineteen rounds of equal width, and the plate reports the widest but not the distribution. On a square table the diagonal lengths rise linearly to the middle and fall again, so half the rounds have fewer than half the peak’s cells, and a machine sized for the peak is idle for most of the run. That is a real inefficiency with an exact description available from what is already computed, and it is the sort of thing on average is not a number is about — a mean over rounds hides a shape that decides the answer.

And the word machine is a different question. A column computed in machine words computes sixty-four cells in one machine word, which is parallelism of a kind this counter cannot see at all — it is inside the operation rather than between operations, and the span of a Myers column is the number of columns whatever the word size. Two kinds of parallelism, one visible here and one visible in that essay’s count of word operations, and no single number holds both.

Where this ladder goes next: the cells that were never worth having

Everything on this page takes the cell count as given and asks what can be done about the order. The other question is whether the cells were the right cells.

The recurrence’s subproblem set — every pair of prefixes — is a choice, and it is the obvious choice rather than a forced one. For a longest common subsequence, only the cells where the two characters agree can lengthen anything; there are rr of those and rr is about nm/σnm/\sigma for an alphabet of σ\sigma symbols. A method that enumerates exactly those pairs and places each one by a search over the answers found so far computes rr subproblems rather than nmnm, which on English text is a twenty-fifth of the rectangle.

Two things make that the right next rung. It is a change to the first factor of the cost — the one this field has treated as fixed since it started counting cells — where the previous two rungs both attacked the second. And it fails informatively: on a two-letter alphabet rr is about half of nmnm and the method is strictly worse than the grid it replaces, by the logarithm it added. A technique whose losing case is as easy to exhibit as its winning one is worth having on a site that measures rather than recommends.

What this makes readable

Essays that name this one as a prerequisite.

Named alongside this one

Essays reaching for the same objects. Nobody chose these; they are what the concept index makes visible.

What links here

Every essay whose body links to this one.

The objects this essay names

Each one links to every other essay that touches it.

Counted primitiveDependency graphDynamic programmingEdit distanceEvaluation orderMeasured countParallelismRecurrenceSpanSubproblemTrade offWork