What the machine does

A column computed in machine words

Adjacent cells of a distance table differ by at most one, so a whole column is two bits per cell — and thirty-two of them fit in one register. Fifteen word operations per character replace three cell evaluations per cell, and below a pattern of fifteen characters the trade is a loss.

Two cells side by side in an edit-distance table differ by at most one.

That is not in the definition and it is not obvious from it. It follows from the recurrence: the cell to the right can always be reached from this one by one insertion, so it is at most one more; and this one can be reached from it by one deletion, so it is at most one more than that. The same argument runs vertically. A diagonal neighbour differs by zero or one.

So a column of the table is not a list of numbers between zero and nn. It is a list of differences from {1,0,+1}\{-1, 0, +1\}two bits a cell — and thirty-two of them fit in one machine register.

The same table as horizontal differences: every cell is −1, 0 or +1The distance table for kitten against sitting, with each cell showing how it differs from its neighbour to the west rather than what it holds. Every difference is −1, 0 or +1: a step of the recurrence changes the distance by at most one in each direction, which is not obvious from the definition and is what makes the column compressible. Two bits a cell, so sixty-four cells fit in two 64-bit registers.sittingkitten111111101111110-1111110-1-111110-1-1-11110-1-1-10110-1-1-10-11one unit = one subproblem given a value-1, 0, 1 — 3 values, 2 bits each
Fig. 1 The kitten against sitting table with each cell showing how it differs from its neighbour to the west, rather than what it holds. Every cell is −1, 0 or +1. The values in this figure and the values in the ordinary plate of the same table carry exactly the same information, and one of them fits in two bits.

Why the unit has to change before anything can be said

Counting cells is useless here, because every cell is still computed. Myers’s algorithm prunes nothing, skips nothing and approximates nothing: it produces the identical table, cell for cell, and its whole claim is that it produces a column at a time.

So the count that means anything is the number of word operations, and a word operation needs a word size to be defined. This site has made that move twice before. The machine field models a cache with a stated line size and counts misses; it models a two-bit branch predictor and counts mispredictions. Neither is a measurement of a real processor and both are exact, reproducible and machine-independent — which is what a cost model is for.

This field adds a third: a bit vector held in ww-bit lanes, charging one operation per lane per act. Every and, or, not, shift and addition on a vector of mm bits costs m/w\lceil m/w \rceil. The implementation of Myers’s recurrence measured here performs fifteen such acts per character of the text, so its total is 15nm/w15\,n\lceil m/w\rceil, and each of those three factors is on the plate.

Word operations, against the size of a wordThe same pair of strings measured on machines whose word is 4, 8, 16, 32 bits wide. The count falls in proportion — halving the word doubles the operations — and the answer does not move, which is what makes this a unit rather than a number about one implementation.1010⁵bits in a wordword operationsMyers over 240 characters · -0.97one unit = one subproblem given a valueword operations, w from 4 to 32
Fig. 2 The same pair of strings on machines with four different word sizes. 108,900 operations at eight bits, 54,450 at sixteen, 29,040 at thirty-two — halving, except for the last step, where 240/32=8\lceil 240/32 \rceil = 8 rather than 7.5 and the ratio comes out at 1.875. The distance is 12 at every point on this axis, which is what makes the count a unit rather than a property of one implementation.

What the fifteen operations are doing

The recurrence works on two vectors: VP, whose bit ii is set where the vertical difference at row ii is +1+1, and VN, set where it is 1-1. Where neither is set the difference is zero. A third pair, HP and HN, carries the horizontal differences.

Per character of the text, the algorithm computes a mask of the positions where that character matches the pattern, combines it with the two vectors by a fixed sequence of bitwise operations, and reads the bottom bit to update a running score. Fourteen of the fifteen operations are bitwise and take no notice of their neighbours.

The fifteenth is an addition, and it is the interesting one. Addition is the only operation in the set that propagates information along the vector, because a carry moves upward through the bits — and propagating information along the column is exactly what the inner loop of the ordinary algorithm was doing. The carry chain is the loop, executed by the adder in one step. That is the whole trick, and it is why this technique appears wherever a scan-like dependency can be expressed as a carry.

The same table as vertical differences: every cell is −1, 0 or +1The distance table for gattacagt against gactacgat, with each cell showing how it differs from its neighbour to the north rather than what it holds. Every difference is −1, 0 or +1: a step of the recurrence changes the distance by at most one in each direction, which is not obvious from the definition and is what makes the column compressible. Two bits a cell, so sixty-four cells fit in two 64-bit registers.gactacgatgattacagt1-1-1-1-1-1-1-1-1-111-1-1-1-1-1-1-1-11110-1-1-1-1-1-1111100000-111111-1-1-1-10111011-1-1-1-111111110-1-111111110101111011100one unit = one subproblem given a value-1, 0, 1 — 3 values, 2 bits each
Fig. 3 The vertical differences over a different pair, which is the direction the vectors hold. A column of this plate is one column of VP and VN together: the shaded cells one way are the bits of VP, the other way VN, and the pale cells are where neither is set. Reading a column downwards and adding gives the ordinary table back.

What it buys, measured

At five hundred and twelve characters each way, the plain table considers 787,456 transitions across 263,169 cells. Myers performs 122,880 word operations at w=32w = 32.

length cells transitions word operations, w=32w = 32 transitions per word operation
64 4,225 12,416 1,920 6.47
128 16,641 49,408 7,680 6.43
256 66,049 197,120 30,720 6.42
512 263,169 787,456 122,880 6.41

The right-hand column is flat, which is the claim: the ratio is 3w/15=6.43w/15 = 6.4, and neither the strings nor their contents move it. Against cells rather than transitions the factor is 2.14, or w/15w/15, and which of the two numbers is the honest one depends on what a cell is thought to cost — this site counts both for exactly that reason.

Word operations, against the length of the stringsMyers, 32-bit words at a measured slope of 2.00; Myers, 8-bit words at a measured slope of 2.00. The strings are unrelated, over an alphabet of 4. On these axes a slope of 2 is a rectangle filled and a slope of 1 is a line.10010⁴10⁵length of each stringword operationsMyers, 32-bit words · 2.00Myers, 8-bit words · 2.00one unit = one subproblem given a valueword operations, n from 64 to 512
Fig. 4 Word operations against the length of the strings, at two word sizes. Both are at slope 2.00 — the product nmnm is still there and nothing about it went away — separated by a constant factor of four, which is the ratio of the word sizes. Bit-parallelism does not change the class. It changes the constant, by a factor equal to the width of a register.
Transitions considered, against the length of the stringsFull table at a measured slope of 2.00. The strings are unrelated, over an alphabet of 4. On these axes a slope of 2 is a rectangle filled and a slope of 1 is a line.10010⁵length of each stringtransitions consideredFull table · 2.00one unit = one subproblem given a valuetransitions considered, n from 64 to 512
Fig. 5 And the quantity it is being set against: transitions considered by the plain table, at slope 2.00 as well. The two plates have the same shape and different units, which is why the comparison above is made as a ratio in a table rather than as two lines on one axis. A plate with two units on one axis would be a picture of an arithmetic mistake.

Reading the answer off the bottom bit

One detail is worth following because it explains why the score is maintained rather than computed.

The vectors hold differences, so nothing in them is a distance. The distance at the bottom of the current column is kept as an ordinary integer, initialised to mm — the distance between the whole pattern and the empty prefix of the text — and updated by one per character according to the top bit of the horizontal difference vectors: up if that bit is set in HP, down if it is set in HN, unchanged otherwise.

So the running score is a scalar that moves by at most one per step, and the whole column’s worth of information never has to be summed. That is what makes the per-character cost a constant number of word operations rather than a constant plus a popcount, and it is also what limits the algorithm to the bottom row: any other row’s value would need the differences above it added up, which is a scan the representation deliberately does not do.

The other consequence is that the intermediate scores are available for free. The score after jj characters of the text is the distance between the whole pattern and the first jj characters of the text, so one run produces the entire last row of the table — which is exactly what the divide step of a linear-space alignment needs, and is why the two techniques compose without either of them being modified.

The crossover, which is where the honest half is

A vector of mm bits occupies m/w\lceil m/w\rceil lanes, and a lane is a whole word whether or not it is full. So the cost per text character is 15m/w15\lceil m/w \rceilflat in mm until mm crosses a multiple of the word size, and then it steps.

Holding the text at 256 characters and sweeping the pattern:

pattern length mm lanes word operations cells transitions
8 1 3,840 2,313 6,408
16 1 3,840 4,369 12,560
32 1 3,840 8,481 24,864
64 2 7,680 16,705 49,472
128 4 15,360 33,153 98,688

At a pattern of eight characters the word machine performs 3,840 operations where the table has 2,313 cells. It does more elementary work than the thing it replaces. The crossover in cells is between eight and sixteen characters, at m+1=15m + 1 = 15; against transitions it is at m+1=5m + 1 = 5, so on any pattern longer than four characters it is already ahead by the count that charges three per cell.

That shape is familiar on this site and it is the reason this essay sits in the machine field rather than in the tables field. A search with no branch to miss measured a branchless binary search doing strictly more work by every counter the site owns and existing because a mispredicted branch costs more than the work it avoids. Bit-parallel edit distance is the same argument with a different resource: it does more, in a unit that is cheaper, and the ranking flips only once the unit is stated.

Word operations, against the length of the shorter stringMyers, 32-bit words at a measured slope of 0.63. One string is held at 512 characters and the other is swept. A count that rises in steps rather than smoothly is a count of whole words, and the step is where the shorter string crosses a lane boundary.1010010⁴length of the shorter stringword operationsMyers, 32-bit words · 0.63one unit = one subproblem given a valueword operations, m from 8 to 256
Fig. 6 Word operations against the length of the shorter string, with the longer one fixed at 512. The line is a staircase: flat while the vector fits in one lane, stepping when it does not. A count that rises in steps rather than smoothly is the signature of a whole-word unit, and it is the single most useful thing this plate says — it means adding a character to a pattern of 33 costs nothing and adding one to a pattern of 32 costs a whole lane.
Transitions considered, against the length of the shorter stringFull table at a measured slope of 0.99. One string is held at 512 characters and the other is swept. A count that rises in steps rather than smoothly is a count of whole words, and the step is where the shorter string crosses a lane boundary.1010010⁵length of the shorter stringtransitions consideredFull table · 0.99one unit = one subproblem given a valuetransitions considered, m from 8 to 256
Fig. 7 The table’s transitions on the same axis: a straight line at slope 0.99, because a cell is a cell and there is no boundary anywhere for it to cross. The two plates together are the crossover, and the crossing point is not a property of either algorithm alone — it is a property of the word size, which is why it is printed.

The other thing two bits a cell is good for

The delta representation is worth a paragraph on its own account, independently of the algorithm, because it is a statement about how much information a distance table contains.

A table of distances between prefixes of two strings of length nn holds (n+1)2(n+1)^2 numbers, each up to nn, so writing it out costs about n2log2nn^2\log_2 n bits. Writing out the differences costs 2n22n^2 — the first row and column, plus two bits a cell. At n=1,000n = 1{,}000 that is a factor of ten, and the two representations are exactly interconvertible: a prefix sum recovers the table, and a difference recovers the deltas.

That is the same observation the coding field makes about a stream whose symbols are correlated — the model is the compressor — arriving here as a property of a computed object rather than of a data source. The table looks like it holds logn\log n bits a cell and holds two, because its cells are heavily constrained by each other, and the constraint is a consequence of the recurrence rather than of anything about the strings.

Where the same trick is used

Bit-parallelism over a dynamic programming column is one instance of a family, and the family is worth naming because the shape recurs.

Shift-Or, for exact matching. A bit vector of pattern positions, shifted left and masked by the character’s match set, one operation per text character. It is the same representation with a simpler recurrence, it predates Myers, and it is the reason the technique is sometimes called bitap.

Approximate matching with a small threshold. k+1k+1 vectors, one per allowed error, each derived from the one below it. Cheaper than the full Myers recurrence when kk is tiny and worse when it is not, which is a crossover of the same kind as the one above.

Carry propagation as a scan. The general form: any left-to-right dependency where the state is one or two bits per position and the update is monotone can often be expressed as an addition, and then a whole word of positions advances in one step. That is what the fifteenth operation is doing here, and it is why the technique fails on recurrences whose per-cell state does not fit in a couple of bits — the affine gap model, for instance, needs three tables and the deltas stop being small.

What the model does and does not claim

The word machine here is a model, in the exact sense the cache model and the branch predictor on this site are models, and it is worth stating what that buys and what it costs.

What it buys: an exact, reproducible, machine-independent count. Run the same pair of strings through the same code at the same word size on any host and the number of word operations is the same integer. That is the same property comparisons have, and it is why every number in this essay is a count rather than a duration.

What it costs: the model charges one for every operation on a lane, and a real processor does not. An addition with a carry chain across eight lanes is not eight independent additions — it is a dependency the hardware serialises — while eight independent ands are not, and a vector unit may do thirty-two lanes at once. So the count here is an upper bound on the parallel work and an accurate count of the scalar work, and it does not model the one thing that would make a wider register strictly better.

That is a real limitation and it is stated rather than hedged. What the model does support is the claim this essay makes: the count is proportional to nm/wn\lceil m/w\rceil, it is a staircase in mm, and the crossover against a plain table is at a pattern length the model computes exactly.

The empty half of the register

The staircase says that a pattern of nine characters costs a whole lane, of which seven-eighths is unused. That waste is not inherent, and the repair is worth stating because it applies exactly where the technique is weakest.

Nothing about the recurrence requires a lane to hold one pattern. The vectors are bitwise throughout except for the single addition, and an addition is the only operation whose effect crosses a bit boundary. So several short patterns can be packed into one register — each occupying its own field, separated by a spare bit that absorbs the carry — and advanced together on the same text character. Three nine-bit patterns and their separators fit in a thirty-two bit word, and one pass over the text then computes three distances.

The gain is exactly the fraction of the register that was empty. At a pattern of nine on a thirty-two bit machine that is a factor of three; at a pattern of six it is four. The technique’s worst regime and its best opportunity for packing are the same regime, which is a pleasant symmetry and not a coincidence — both are the same statement about how much of the register the problem fills.

Two conditions, and both are checkable rather than hopeful. The separator bit must be wide enough that no carry escapes its field, which for this recurrence means one spare bit per pattern because the addition can propagate at most one position beyond the field’s top. And the running scores are per pattern, so the scalar bookkeeping is multiplied rather than shared — a small cost, since the scalars are integers and the expensive part was the vector.

Where this matters is the case the crossover section makes look bad. A spell-checker compares one mistyped word against thousands of dictionary entries, all of them short, and the plain analysis says the word machine is barely ahead of the table at those lengths. Packed, it processes several dictionary entries per pass and is ahead by the packing factor as well. The regime in which the ordinary form is unimpressive is precisely the regime that is plural, and plural is what packing is for.

The table that has to be built before the first character

Every count in this essay is per character of the text, and there is a term that is not.

The recurrence needs, for each character of the text, a mask saying which positions of the pattern hold that character. Those masks are precomputed: one bit vector per symbol of the alphabet, each m/w\lceil m/w \rceil lanes wide, built by one pass over the pattern before the text is touched.

So the real cost is

σmw  +  15nmw\sigma \left\lceil \frac{m}{w} \right\rceil \;+\; 15\,n \left\lceil \frac{m}{w} \right\rceil

and the first term is invisible in every table above because those tables hold σ\sigma at four or twenty-two while nn is in the hundreds. Divide through and the preprocessing is worth paying once the text is longer than about σ/15\sigma/15 characters — seventeen characters for a byte alphabet, which is never a consideration.

It becomes one on a wide alphabet. Over sixteen-bit characters the mask table is sixty-five thousand vectors and the break-even text is some four thousand characters long; below that, the algorithm spends most of its time preparing for a text it barely reads. And the table is rebuilt for every new pattern, so a workload of many short searches pays it many times.

The repair is the same one the multi-pattern automaton needs and arrives for the same reason. A symbol occurring nowhere in the pattern has an all-zero mask, and all such symbols are identical, so only the symbols the pattern actually contains need entries — at most mm of them — with everything else resolving to a shared zero vector through a small map. The preprocessing term becomes O(m)O(m) rather than O(σ)O(\sigma), it no longer depends on the alphabet at all, and the per-character cost gains one lookup.

Which restores the property the essay’s headline claim depends on. Without it, the cost is a function of nn, mm, ww and σ\sigma, and the last of those appears in no statement of the algorithm; with it, the alphabet genuinely drops out. That is a term worth chasing down rather than absorbing into a constant, because a term that is negligible on the alphabet a paper measured and dominant on the alphabet a reader has is the exact shape of thing this collection exists to print.

What it does not do

Three things, and all three are the reason this is a technique rather than a replacement.

It gives the distance and not the alignment. The vectors hold differences, the score is a running integer, and nothing is retained that a traceback could walk. Recovering the alignment means going back to a table — which is what the alignment that fits in one line is for, and the two techniques compose: the divide step can use the bit-parallel routine to compute the row it needs.

It computes every cell. There is no output sensitivity here at all. On two strings one edit apart it does exactly as much work as on two unrelated strings, where a band as wide as the answer does a hundredth. The two techniques attack different factors of nmnm — one the constant, one the nn — and real implementations use both, running the bit-parallel recurrence inside a band.

Its constant is not small. Fifteen operations per character is what this implementation performs; published versions are nearer eleven, and a hand-tuned one fewer still. The count reported here is a count of what the measured implementation actually did, not a quotation, and it is the number the plates carry. A different implementation would move the crossover and would not move the shape.

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

The 8 essays that link to this one and share the most of its objects, of 15 that link here.

The objects this essay names

Each one links to every other essay that touches it.

Bit-parallelBranchlessCarry propagationCost modelCrossoverDynamic programmingEdit distanceLocalityMachine wordMeasured countSubproblemWord size