Counting

A run end kept in a register

A selection sort's record of adjacent order spends about a word read on every question it is asked, and on short runs it is asked 184 questions for every comparison it saves, so no filter read in that word can make it pay. Every question starts from one of the sort's two current extremes, and what the record can say about all of them is one number: where the run from that extreme ends. Kept in a register beside each extreme and refreshed only when it changes, that number cuts the reading to a forty-fifth on 1,024 keys in runs of four, and the price of a saved comparison from 201 word reads to 4.5, where it stops growing with the input.

A filter that reads the word it saves found the floor under a record’s price. The two-ended selection sort keeps, after a pass between neighbours, a record of two bits a neighbouring pair saying which way each pair points, and a question about positions i<ji < j is answered without a comparison when every pair from ii to j−1j - 1 points one way. On 1,024 keys in sorted runs of four, the sort asks its record 184 questions for every comparison the record saves, and any record read at least once a question pays at least that many reads a saving. The plain record read 1.094 words a question and so 201 a saving; a filter bit beside each pair, read in the same word, turned away two thirds of the questions and brought the price only to 185.

Its closing section looked at where the questions come from. The sort scans the keys still unsorted for the smallest and the largest, so every question it asks starts from its current minimum or its current maximum, positions it already holds in registers, and it asks hundreds of questions from each before either changes. What the record can say about all of those questions is one number: how far the run starting at the extreme reaches. A question about jj is answerable exactly when jj lies inside that run. A sort could find the run’s end once, by reading the record from the extreme to the run’s first break, keep it in a register, and answer every later question from that extreme with one comparison of jj against the register, reading nothing. The register is stale, and must be refilled, when the extreme moves or when a pair inside its run, or the break that ends it, changes.

The prediction was that on runs of four keys the reads would fall from about one word a question to about one word for every change of extreme, that the price a saved comparison would fall from 185 to under ten at 1,024 keys and stop growing with the input, and it named the risk: on long runs each pass’s two swaps break the run the register holds, and every break forces a rescan of the whole run.

All three hold.

Two registers beside the two extremes

The sort, its pass, its chains of past minima and maxima, the inputs and the record of two bits a pair are the earlier essays’, and the charging changes nothing about the sort or its answers. Two registers are added, one for each of the last two positions questions were asked from, which in practice are the current minimum and maximum. A question from a position with a valid register reads no word of the record. A question from any other position fills a register: it reads the record from that position to the first pair that breaks the run, a word for every sixteen pairs it crosses, keeps the run’s last pair in the register, and evicts the older of the two.

A register is dropped whenever the record changes inside the run it describes or at the pair just past its end, because then the run may have grown or broken. That happens when a scan compares two neighbours and records their order, and when the swaps at the end of a scan move a key and the record forgets the two pairs around it. Every time a question finds a register valid, the run end it holds is checked against a fresh scan of the record, and it has matched on every question of every input.

A forty-fifth of the reading

On 1,024 keys in runs of four, two registers holding the run end from each extreme bring the record's reading from 1.094 words a question to 0.024, a forty-fifth; the registers read more than the plain record only on a sorted array, where each pass's swaps break the long runs they holdThe two-ended selection sort with its pass first, on 1,024 keys in sorted runs of 4 keys to the whole array: words a question read by the record of two bits a pair, words a question read by the two registers' scans (a question from a position with a valid register reads none), and the run list's binary-search probes. runs of 4: bits 1.094, registers 0.024 (98% of questions from a valid register), list 8.80; runs of 8: bits 1.119, registers 0.026 (98% of questions from a valid register), list 8.01; runs of 16: bits 1.141, registers 0.028 (97% of questions from a valid register), list 7.07; runs of 32: bits 1.425, registers 0.046 (97% of questions from a valid register), list 6.28; runs of 64: bits 1.901, registers 0.097 (96% of questions from a valid register), list 5.74; runs of 128: bits 2.769, registers 0.292 (93% of questions from a valid register), list 4.96; runs of 256: bits 4.204, registers 1.137 (88% of questions from a valid register), list 4.71; runs of 512: bits 5.852, registers 5.374 (74% of questions from a valid register), list 4.51; runs of sorted: bits 22.132, registers 53.541 (0% of questions from a valid register), list 2.00. Logarithmic scale; nothing is under 0.004.keys in each sorted run of the inputreads a question (log scale): words, or probes of the list0.010.111048163264128256512sortedrun list, probestwo bits a pair, wordsregisters, words1,024 keys, a pass firstlogarithmic scale
Fig. 1 Reads a question on 1,024 keys, against the length of the input’s sorted runs, on a logarithmic scale. The registers: 0.024 words on runs of four, 0.028 on runs of sixteen, 0.097 on runs of 64, 1.14 on runs of 256, 5.37 on runs of 512, 53.5 on a sorted array. Two bits a pair, read every question: 1.094, 1.141, 1.90, 4.20, 5.85, 22.1. The run list: 8.80, 7.07, 5.74, 4.71, 4.51, 2.00 probes.

On 1,024 keys in runs of four, the two registers read 0.024 words a question, against 1.094 for the record read on every question: a forty-fifth. On runs of sixteen keys they read 0.028 against 1.141, and on runs of 64 keys 0.097 against 1.90. Ninety-eight per cent of the sort’s questions on short runs are asked from a position whose register is valid, and read nothing.

The registers read more than the plain record only on a sorted array at this size, and nearly as much on runs of 512 keys, 5.37 words against 5.85. That is the failure the closing section named, and it is confined to the inputs where the run list is cheaper than either.

A price that stops growing

With the registers the record spends 4.50 word reads for each comparison it saves on 1,024 keys in runs of four, against 201 without them, and 4.39 at 4,096 keys against 764: the price stops growing with n, and on runs of sixteen it is 1.64, under the 3.1 reads at which a table of compared pairs broke evenWord reads a saved comparison — all the record's reading divided by the comparisons it removes — for the record of two bits a pair read on every question (dashed) and with the two registers (solid), at 256, 1,024 and 4,096 keys, on runs of 4, 16 and 64 keys; the grey rule at 3.1 is the break-even an earlier page found for a table of compared pairs. runs of 4: 256 keys 48.35 and 4.11, 1,024 keys 201.42 and 4.50, 4,096 keys 763.89 and 4.39; runs of 16: 256 keys 18.27 and 1.67, 1,024 keys 66.23 and 1.62, 4,096 keys 264.98 and 1.64; runs of 64: 256 keys 8.22 and 2.00, 1,024 keys 30.81 and 1.58, 4,096 keys 122.27 and 1.45.keys sortedword reads for each comparison saved (log scale)141664256break-even of a pair table2561,0244,096runs of 4runs of 16runs of 64dashed: without registersa pass firstlogarithmic scale
Fig. 2 Word reads for each comparison the record saves, without registers (dashed) and with them (solid), at 256, 1,024 and 4,096 keys. Runs of four: 48, 201 and 764 without; 4.11, 4.50 and 4.39 with. Runs of sixteen: 18, 66 and 265 without; 1.67, 1.62 and 1.64 with. Runs of 64: 8.2, 31 and 122 without; 2.00, 1.58 and 1.45 with. The grey rule at 3.1 is the break-even of a table of compared pairs.

With the registers the record spends 4.50 word reads for every comparison it saves on 1,024 keys in runs of four, against 201 without them, and 4.39 at 4,096 keys against 764. The price without registers grows fourfold with each fourfold growth of the input; with them it does not grow at all, 4.11, 4.50 and 4.39 at the three sizes. On runs of sixteen keys it is 1.62 to 1.67 at every size and on runs of 64 keys 1.45 to 2.00.

That puts the record below the line it had never come near. The price of remembering an answer found that a table of the pairs a selection sort had already compared pays for itself once a comparison costs more than about three word operations. Read on every question, the record of adjacent order was fifteen to two hundred and forty times above that on short runs. With the registers it is under it on every input with runs of sixteen keys or more, and within a factor of one and a half of it on runs of four.

Both of the record’s costs at once

The plain record had two ways of spending words, and the earlier essays found each in turn. A question it cannot answer costs the word holding its first pair, and on short runs that is nearly every question; the filter attacked that cost and found it was a floor. A question it can answer costs a word for every sixteen positions between ii and jj, and on long runs that is the dominant cost, 1.90 words a question on runs of 64 keys at 1,024 keys, when the record answers only one question in sixteen. The registers remove both at once. A question from a valid register reads nothing whether it is answerable or not, and however far jj is from ii, because the register already holds how far the run reaches and the answer is one comparison with it.

On runs of 64 keys that turns 1.90 words a question into 0.097, a twentieth, and on runs of 128 keys 2.77 into 0.29. The scan across an answer is still paid, but once a fill instead of once a question, and the sort asks a few hundred questions from each fill on these inputs.

None of this costs the record any memory, unlike the ring of a pass’s minima or a cache of compared pairs that forgets on purpose. The record is still 64 words of two bits a pair at 1,024 keys. The registers are four machine words beside the two positions the sort already keeps, and they hold nothing the record does not hold; they hold it in the one place the sort reads for nothing.

Why the price stops

A register is filled 12.05 times a scan of the sort on 1,024 keys in runs of four and 12.22 at 4,096, while the record saves 2.81 and 2.92 comparisons a scan: both grow slowly with n, which is why the price a saving stops growingFor each of the sort's n/2 scans, the times a register is filled by a scan of the record (solid) and the comparisons the record saves (dashed), at 256, 1,024 and 4,096 keys on runs of 4, 16, 64 and 256 keys. runs of 4: 256 keys 11.88 filled, 3.01 saved, 1,024 keys 12.05 filled, 2.81 saved, 4,096 keys 12.22 filled, 2.92 saved; runs of 16: 256 keys 13.89 filled, 8.70 saved, 1,024 keys 14.00 filled, 9.07 saved, 4,096 keys 13.93 filled, 8.97 saved; runs of 64: 256 keys 26.52 filled, 32.56 saved, 1,024 keys 23.18 filled, 33.40 saved, 4,096 keys 22.02 filled, 33.32 saved; runs of 256: 1,024 keys 70.17 filled, 133.98 saved, 4,096 keys 56.62 filled, 130.31 saved.050100150keys sorteda scan of the sort: registers filled (solid), comparisons saved (dashed)2561,0244,096runs of 4runs of 16runs of 64runs of 256a pass firstper scan of the sort
Fig. 3 For each of the sort’s n/2 scans, the registers filled by a scan of the record (solid) and the comparisons the record saves (dashed). Runs of four: 11.9, 12.1 and 12.2 filled and 3.0, 2.8 and 2.9 saved at 256, 1,024 and 4,096 keys. Runs of sixteen: about 14 filled and 9 saved. Runs of 64: 22 to 27 filled and 33 saved. Runs of 256: 57 to 70 filled and 130 saved.

A register is filled about twelve times a scan of the sort on runs of four keys, at every size from 256 keys to 4,096, and the record saves about three comparisons a scan. Both numbers are flat in nn. That is why the price stops growing: the questions grow with nn, a scan asks about every key it passes, but the registers make the questions free, and what costs reads is filling them, which happens a fixed number of times a scan.

A register is filled when the extreme it describes moves, or when the record changes inside its run. The extreme of a random stretch moves about ln⁡n\ln n times a scan, which grows, but slowly: from 256 to 4,096 keys ln⁡n\ln n rises by half, and twelve fills a scan rise by about a thirtieth. So most fills are not moves of the extreme. By elimination they are changes inside a register’s run: a scan’s comparison of two neighbours that extends or breaks the short run next to an extreme, which happens at a rate set by the runs’ length, not by nn. The registers do not record which kind of event refilled them, so that split is inferred rather than counted. Each fill reads about one word, since a run of four keys rarely crosses a word boundary, so the reading a scan costs about twelve words, and the savings a scan are three comparisons. The ratio is four, at every size.

The prediction said the reads would fall to about one word for every change of extreme, and that the extremes change about as often as the record saves a comparison. The first is right if a change of extreme is read as any change to what a register describes; the second is off by a factor of four, which is the price that results.

Where the registers stop holding

On long runs the registers stop holding: the share of questions asked from a valid register falls from over 95% on runs of 64 keys to 74% on runs of 512 at 1,024 keys and to nothing on a sorted array, where every pass's two swaps break the one run the register holds and its rescans read 53.54 words a question against the plain record's 22.13At 256, 1,024 and 4,096 keys, on runs of 64 keys up to a sorted array: the share of the record's questions asked from a position whose register is still valid, and the words a question the registers and the plain record read. 256 keys: 64 83% valid, 0.43 against 1.74; 128 70% valid, 1.59 against 2.18; sorted 0% valid, 13.54 against 6.12. 1,024 keys: 64 96% valid, 0.10 against 1.90; 128 93% valid, 0.29 against 2.77; 256 88% valid, 1.14 against 4.20; 512 74% valid, 5.37 against 5.85; sorted 0% valid, 53.54 against 22.13. 4,096 keys: 64 99% valid, 0.02 against 1.96; 128 98% valid, 0.06 against 2.94; 256 97% valid, 0.21 against 4.74; 512 95% valid, 0.84 against 8.01; 1024 90% valid, 3.92 against 13.02; 2048 76% valid, 19.74 against 18.81; sorted 0% valid, 213.54 against 86.13.00.2500.5000.7501keys in each sorted run (the last of each size is a sorted array)share of questions from a valid register64128256512102420484096256 keys1,024 keys4,096 keysa pass firstshare of all questions
Fig. 4 On runs of 64 keys up to a sorted array, the share of the record’s questions asked from a valid register. At 1,024 keys: 96% on runs of 64, 88% on runs of 256, 74% on runs of 512, none on a sorted array, where the registers read 53.5 words a question against the plain record’s 22.1. At 4,096 keys: 99%, 97%, 95%, 90% on runs of 1,024, 76% on runs of 2,048, none sorted.

On a sorted array of 1,024 keys no question is ever asked from a valid register, and the registers read 53.5 words a question against the plain record’s 22.1. The closing section’s named failure is exact. A sorted array is one run, every scan’s swaps at its two ends break that run, the break forgets the pairs around the swapped keys, and the next question from the new extreme refills a register by scanning the whole remaining run, n/2n/2 positions on average, sixteen to a word. The plain record reads only as far as each question’s jj.

The decline is gradual. At 1,024 keys the share of questions from a valid register is 96% on runs of 64 keys, 88% on runs of 256 and 74% on runs of 512; at 4,096 keys it stays above 90% up to runs of 1,024. A register fails when its run is long enough that a pass is likely to break it, and that depends on how long a run is relative to the part of the array still unsorted. Long runs at a large size are as safe as short runs at a small one, and the reverse holds too: at 256 keys the decline starts earlier, with 83% of questions from a valid register on runs of 64 keys and 70% on runs of 128, and on a sorted array of 256 keys the registers read 13.5 words a question against the plain record’s 6.1.

The cheapest record at every run length

On 1,024 keys the registers are the cheapest way to consult the record on every input with runs shorter than 512 keys, and the run list from there to the sorted array; a sort that reads its run count off the pass and picks pays at most 4.51 reads a question at any run length, against the plain record's 22.13On 1,024 keys, for each run length, the reads a question of the cheapest of the three records — the registers, the record of two bits a pair read on every question, the run list's search — and which one it is; the plain record beside it. runs of 4: registers at 0.024, plain 1.094; runs of 8: registers at 0.026, plain 1.119; runs of 16: registers at 0.028, plain 1.141; runs of 32: registers at 0.046, plain 1.425; runs of 64: registers at 0.097, plain 1.901; runs of 128: registers at 0.292, plain 2.769; runs of 256: registers at 1.137, plain 4.204; runs of 512: list at 4.505, plain 5.852; runs of sorted: list at 1.996, plain 22.132.keys in each sorted run of the inputreads a question of the cheapest record (log scale)0.010.111048163264128256512sortedthe cheapest recorddots: registersdots: the run listtwo bits a pair, plain1,024 keys, a pass firstlogarithmic scale
Fig. 5 On 1,024 keys, the reads a question of the cheapest of the three records at each run length: the registers on runs of 4 to 256 keys, 0.024 to 1.14 words; the run list on runs of 512 keys and the sorted array, 4.51 and 2.00 probes. The plain record of two bits a pair beside it, 1.09 to 22.1 words.

On 1,024 keys the registers are the cheapest way to consult the record on every input with runs shorter than 512 keys, and the run list on runs of 512 keys and a sorted array; a sort that picks between them pays at most 4.51 reads a question on any input measured. The plain record of two bits a pair, which what it costs to consult two bits a pair found the cheaper of its two candidates on every input short of runs of 512 keys, is never the cheapest of the three. The pass that finds the runs already counts them, and that essay showed the count is enough to choose between the bits and the list; the same count chooses between the registers and the list, at the same crossing, between runs of 256 and 512 keys at this size.

The three records hold the same information about adjacent order, and each pays for it differently. The list pays a search proportional to the logarithm of how many runs there are, the bits pay the distance from ii to the answer, and the registers pay for changes: a fill each time the extreme moves or its run is disturbed. On short runs, where changes are cheap and the questions are many, the registers win by forty-five times. On one long run that every pass breaks, changes are expensive, and the list’s two probes win.

What the prediction got right

The closing section predicted that on runs of four keys the reading would fall to about one word for every change of extreme. It falls to 0.024 words a question at 1,024 keys, about twelve fills a scan of one word each. It predicted the price a saved comparison would fall from 185 to under ten at 1,024 keys and stop growing with nn. It falls to 4.50, and it is 4.11, 4.50 and 4.39 at the three sizes. It named the failure on long runs, that each pass’s swaps break the register’s run and force a rescan of all of it, and on a sorted array that failure costs the registers two and a half times the plain record’s reading.

The question it asked was whether the cost of consulting a record belongs to the questions or to the moments when what the record knows about the question’s first position changes. On these inputs it belongs to the changes. The questions grow as n2n^2 and are free; the changes grow as nn and are what the reading costs.

What the counts assume

Registers are free. A register holds a position and a run end, two machine words beside the extremes the sort already keeps, and reading it is charged nothing. On a real machine it is a comparison with a value already in a register, about the cost of the loop’s own bound check, and that is what the essay charges.

Words, not time. As on the earlier pages, a word read is one unit whether it is in cache or not, and nothing was timed.

Two registers. One for each extreme, the older evicted when a question comes from a third position. Questions from a third position are rare in this sort, since every question starts from a current extreme, and a sort with more registers would mostly keep runs nobody asks about again; no other number was run.

Runs of one length. The inputs are sorted runs of a fixed length with interleaved values. Inputs with a mix of long and short runs would sit between the curves here, since each register’s cost depends only on the run its extreme starts.

Still open: a register that survives the swap

The registers fail on long runs for one reason: each scan’s swaps put the extremes at the two ends of the unsorted part, the record forgets the pairs around both swapped positions, and a register whose run passed through either position is dropped and refilled by a scan of the whole run. But a swap does not destroy what the record knew about the run beyond the swapped position. A run from ii to kk that loses its pair at position pp becomes two runs, one from ii to p−1p - 1 and one from p+1p + 1 to kk, and the second is still known in full.

The measurement that follows keeps, when a swap breaks a register’s run, the part of the run on the far side of the break as a register in its own right, rather than dropping it, and charges the sort’s reads on the same inputs. The prediction is that on a sorted array the registers’ reading falls from 53.5 words a question at 1,024 keys to under the plain record’s 22.1, since each scan then rescans only the stretch near the swapped ends, and that nothing changes on short runs, where registers are almost never broken by a swap. It could fail on the extremes themselves. The new minimum after a swap is usually not inside a run the register kept, so the kept part may never be asked about before it is broken again. The question is whether a record can keep what a swap did not destroy cheaply enough to be worth keeping, or whether the run a register holds is only useful for as long as its extreme stays put.

Named alongside this one

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

The objects this essay names

Each one links to every other essay that touches it.

Bit vectorComparison countNatural runPredictionSelection sortSpace time trade