What a bound is

What a pass costs when it is a file

The streaming model trades passes for memory along n to the power one over p, and it never says what a pass costs. On a file a pass is a read of every block, and it cannot run in less than one block of memory. Charge both and the trade nearly disappears: the median of four million keys takes three passes at two blocks of memory and two passes at four, and writing the surviving interval out makes the third pass cost sixteen blocks instead of four thousand. On a heavy tail the same habit nearly doubles the bill.

What a second pass buys measured a trade and deliberately left out its price. An exact median of thirty-two thousand values needs about a million bits of state in one pass, eleven thousand in two and three hundred and twenty in nine: the state falls as n1/pn^{1/p}, and each pass bought is paid for in memory saved. Near its end that essay named where the price would come from. In the external-memory model a pass is n/Bn/B block transfers, so nine passes cost nine times the reading of one. It then declined to set an exchange rate, on the grounds that the ratio between memory and bandwidth belongs to a machine rather than to an algorithm.

That is true, and it hides something that does not depend on the machine. A pass over a file is not only n/Bn/B transfers. It is n/Bn/B transfers through a buffer, and the buffer is memory. A program cannot read a block into less than a block. So the moment a pass is priced as a file, the memory axis acquires a floor: nothing runs in less than one block of BB words. The steep part of the state law — the part that makes passes look like a good buy — lies almost entirely under that floor.

This page makes both charges and measures what is left of the trade.

A floor the streaming model does not have

In the streaming model a pass is free and the only resource is state, so the state law can be read all the way down: nine passes, three hundred and twenty bits. On a file the reading has a unit. A block of 1,024 thirty-two-bit keys is 4 KB, the size of a page on most machines, and it is the least a pass can hold while it reads.

The state p passes need falls under one 1,024-word block at the third pass for a file of 2²² keys and at the fourth for 2⁴⁰: everything the streaming trade offers beyond that is smaller than the buffer a pass is read throughThe state an exact selection needs with p passes, n^(1/p) words, for files of 2²⁰, 2²², 2³⁰, 2⁴⁰ keys, against one block of 1,024 words — 4 KB of 32-bit keys. 2²⁰ keys: 1 pass 1,048,576, 2 passes 1,024, 3 passes 102, 4 passes 32, 5 passes 16, 6 passes 10; the last pass count whose state is above one block is 1. 2²² keys: 1 pass 4,194,304, 2 passes 2,048, 3 passes 161, 4 passes 45, 5 passes 21, 6 passes 13; the last pass count whose state is above one block is 2. 2³⁰ keys: 1 pass 1,073,741,824, 2 passes 32,768, 3 passes 1,024, 4 passes 181, 5 passes 64, 6 passes 32; the last pass count whose state is above one block is 2. 2⁴⁰ keys: 1 pass 1,099,511,627,776, 2 passes 1,048,576, 3 passes 10,321, 4 passes 1,024, 5 passes 256, 6 passes 102; the last pass count whose state is above one block is 3. Logarithmic vertical axis.1010010³10⁴10⁵10⁶10⁸10¹⁰10¹²123456passeswords of state an exact selection needsone 4 KB blockbelow it no pass can run2²⁰ keys2²² keys2³⁰ keys2⁴⁰ keysn^(1/p) words · block 1,024 wordsshaded: below the read buffer
Fig. 1 The state an exact selection needs with p passes, n^(1/p) words, against one 1,024-word block (4 KB); logarithmic vertical axis. For 2²² keys, a 16 MB file: 4,194,304 words in one pass, 2,048 in two, 161 in three. For 2³⁰ keys, 4 GB: 32,768 in two, 1,024 in three. For 2⁴⁰ keys, 4 TB: 1,048,576 in two, 10,321 in three, 1,024 in four. The shaded band is below the read buffer.

The law crosses the block line early. For a file of four million keys the state two passes need is two blocks, and three passes need a sixth of a block. For a file of a thousand million keys, three passes need exactly one block. Even at a trillion keys — four terabytes of them — the fourth pass is where the state reaches the buffer. The number of pass counts that are worth distinguishing is ⌈log⁡n/log⁡B⌉\lceil \log n / \log B \rceil. For every file a single machine holds, that is two, three or four.

Everything the streaming plates drew beyond that — five passes, seven, nine, the three hundred and twenty bits — is state smaller than the buffer the pass must be read through. On a file those points do not save memory. The buffer costs what it costs whatever the counters need, and a selection that could run in 45 words at four passes still needs a thousand of them to read.

Memory decides the passes, and the passes are few

The measurement is exact selection of the median of 4,194,304 uniform keys held in a file of 4,096 blocks. The selector is the narrowing one from the earlier essays: each pass cuts the surviving interval into as many equal-width pieces as memory allows, counts the keys in each and keeps the piece holding the median’s rank, and the run collects — keeps and sorts what is inside the interval — as soon as that fits beside the read buffer. Memory is the parameter and passes are the result. A pass costs two words a piece (a counter and a cut point), and whatever is left after the buffer goes on pieces. Every answer is checked against a sort of the whole file.

Selecting the median of 2²² uniform keys takes three passes from two blocks of memory to 3,072 words and two above that; rereading pays three or two reads of the file, and writing the interval out pays two at every memoryExact selection of the median of 4,194,304 uniform 32-bit keys — 4,096 blocks of 1,024 — with equal-width cuts, against the memory available in words, buffers included. The vertical axis is blocks read plus blocks written, divided by the file's 4,096 blocks. Reread the file every pass: 2,100 words, 3 passes, 3.00; 2,300 words, 3 passes, 3.00; 2,600 words, 3 passes, 3.00; 3,072 words, 3 passes, 3.00; 4,096 words, 2 passes, 2.00; 6,144 words, 2 passes, 2.00; 8K words, 2 passes, 2.00; 16K words, 2 passes, 2.00; 64K words, 2 passes, 2.00; 256K words, 2 passes, 2.00; 2.00M words, 2 passes, 2.00; 4.00M words, 1 pass, 1.00. Write the interval out every pass: 2,100 words, 3 passes, 2.00; 2,300 words, 3 passes, 2.00; 2,600 words, 3 passes, 2.00; 3,072 words, 3 passes, 2.00; 4,096 words, 2 passes, 2.00; 6,144 words, 2 passes, 2.00; 8K words, 2 passes, 2.00; 16K words, 2 passes, 2.00; 64K words, 2 passes, 2.00; 256K words, 2 passes, 2.00; 2.00M words, 2 passes, 2.00; 4.00M words, 1 pass, 1.00. Every answer was checked against a sort of the whole file.01234,09616K64K256K1.00M4.00Mmemory in 32-bit words, both buffers included (logarithmic)blocks moved ÷ blocks in the file3 passes2 passes1 passreread the file every passwrite the interval out everypass4,194,304 keys, block 1,024 wordstwo passes from 4,096 words
Fig. 2 Blocks moved divided by the file’s 4,096 blocks, against memory in words with the buffers included, logarithmic horizontal axis. Rereading the file every pass: three passes and 3.00 from 2,100 words to 3,072, two passes and 2.00 from 4,096 words to half the file, one pass only when the whole file fits. Writing the surviving interval out as it is read: 2.00 at every memory short of the whole file.

From just over two blocks of memory to 3,072 words the median takes three passes. From 4,096 words — four blocks, 16 KB — it takes two, and it goes on taking two until memory holds the entire file, at which point it takes one. Between 16 KB and 8 MB of memory, a factor of five hundred, nothing changes at all. The trade the streaming model drew as a smooth curve is, on a file, one step at four blocks and another at the size of the file.

Those numbers follow from the law with the buffer added. At 2,100 words the buffer leaves 1,073 words for pieces, which is 536 pieces, and 4,194,304 keys divided 536 ways leaves about 7,800 in the median’s piece. That is too many to collect in the room left beside the buffer, so a second narrowing is needed, and then a third pass to collect. At 4,096 words there are 1,534 pieces and about 2,700 keys survive, which fits. The step sits where n/sn/s falls under M−BM - B with s≈(M−B)/2s \approx (M - B)/2, which for this file is just under four blocks.

The pass that reads almost nothing

Rereading is what the streaming model’s passes are: every pass begins at the start of the file. A file allows something a stream does not. A pass can write. It can copy the keys inside the current interval to a new, smaller file while it counts, so that the next pass reads only that.

The second line on the plate does exactly that. It costs a second buffer, one block to write into, and the writes themselves. It is flat at 2.00 file-reads at every memory where rereading costs 3.00.

At 2,100 words — two blocks and a little — rereading moves 12,288 blocks in 3 passes; writing the interval out moves 8,208, and its third pass reads 8 blocks instead of 4,096One exact selection of the median of 4,194,304 uniform keys with 2,100 words of memory, 1,024-word blocks, each pass's blocks read and written. Reread the file every pass: pass 1 counts 536 pieces, reads 4,096, writes 0, leaving 7,721 keys in the interval; pass 2 counts 536 pieces, reads 4,096, writes 0, leaving 15 keys in the interval; pass 3 collects, reads 4,096, writes 0, leaving 15 keys in the interval; 12,288 blocks in all. Write the interval out every pass: pass 1 counts 536 pieces, reads 4,096, writes 0, leaving 7,721 keys in the interval; pass 2 counts 24 pieces, reads 4,096, writes 8, leaving 314 keys in the interval; pass 3 collects, reads 8, writes 0, leaving 314 keys in the interval; 8,208 blocks in all.reread the file every passpass 1, 536 pieces4,096pass 2, 536 pieces4,096pass 3, collect4,096write the interval out every passpass 1, 536 pieces4,096pass 2, 24 pieces4,096 + 8pass 3, collect8blocks readblocks written4,194,304 keys, 4,096 blocks2,100 words of memory
Fig. 3 One selection at 2,100 words of memory, pass by pass. Rereading: three passes, each reading all 4,096 blocks, 12,288 in all; the first two narrow to 7,721 keys and then to 15. Writing out: the first pass narrows to 7,721 keys, the second reads the file and writes those 7,721 keys to 8 blocks while it counts, and the third reads those 8 blocks — 8,208 blocks moved in all.

The trace shows what happens. The first pass cannot write anything useful, because until it has counted, the interval is the whole file. The second pass knows the interval from the first pass’s counts, so as it reads it copies the 7,721 keys inside it — eight blocks — to a new file. The third pass reads those eight blocks. The whole third pass costs sixteen transfers where rereading pays 4,096. The saving is in blocks moved, which a count of the selector’s own comparisons does not see — the gap the count is not the time keeps a second counter for.

So a third pass on a file is nearly free, and the price the streaming model’s trade was waiting for turns out to be close to zero. With the interval written out, two passes and three cost the same, 2.00 reads of the file plus a few blocks. The memory difference between them, four blocks against two, buys nothing a transfer count can see. The pass count ceases to be a cost at all. What remains is two full reads of the file, and that is the real price of exact selection against a file with more than a few blocks of memory: the first pass to find where to look, and the second to look.

The second buffer has a price that the trace also shows. At 2,100 words, one block for reading and one for writing leave 49 words for pieces, so the writing pass counts 24 pieces rather than 536. It narrows less, and its survivors are 314 rather than 15. That does not matter here, because 314 keys fit in memory at once. It would matter if memory were a few words smaller: a second buffer taken from a memory of barely two blocks is most of what was left for the pass’s own state.

That is the practical reading of sorting what will not fit turned to selection. External merge sort writes its runs out because every key has to be placed, and runs twice as long as memory is the page on how much a longer run saves when every key is written anyway. Selection needs only the keys near one rank, so what it writes shrinks by the fan-out each pass, and the sum of those writes is a geometric series dominated by its first term.

Where writing out costs more than it saves

The plate above is uniform keys, and uniform keys are the case where equal-width cuts narrow by exactly the fan-out. The earlier essay found the rule that needs no data collapses on a heavy tail. A Pareto distribution puts nearly all its mass in a tiny fraction of the range, so an equal-width cut narrows the range and not the count. On a file that failure has a second cost.

On Pareto keys with equal-width cuts, writing the interval out costs up to 7.64 reads of the file where rereading costs 4.00Exact selection of the median of 4,194,304 Pareto 32-bit keys — 4,096 blocks of 1,024 — with equal-width cuts, against the memory available in words, buffers included. The vertical axis is blocks read plus blocks written, divided by the file's 4,096 blocks. Reread the file every pass: 2,100 words, 4 passes, 4.00; 2,300 words, 4 passes, 4.00; 2,600 words, 4 passes, 4.00; 3,072 words, 3 passes, 3.00; 4,096 words, 3 passes, 3.00; 6,144 words, 3 passes, 3.00; 8K words, 3 passes, 3.00; 16K words, 3 passes, 3.00; 64K words, 3 passes, 3.00; 256K words, 2 passes, 2.00; 2.00M words, 2 passes, 2.00; 4.00M words, 1 pass, 1.00. Write the interval out every pass: 2,100 words, 6 passes, 7.64; 2,300 words, 4 passes, 5.95; 2,600 words, 4 passes, 5.72; 3,072 words, 4 passes, 5.16; 4,096 words, 3 passes, 4.26; 6,144 words, 3 passes, 4.07; 8K words, 3 passes, 4.03; 16K words, 3 passes, 4.00; 64K words, 2 passes, 2.99; 256K words, 2 passes, 2.92; 2.00M words, 2 passes, 2.55; 4.00M words, 1 pass, 1.00. Write it out when it has halved: 2,100 words, 4 passes, 4.00; 2,300 words, 4 passes, 4.00; 2,600 words, 4 passes, 3.58; 3,072 words, 3 passes, 3.00; 4,096 words, 3 passes, 3.20; 6,144 words, 3 passes, 3.06; 8K words, 3 passes, 3.03; 16K words, 3 passes, 3.01; 64K words, 3 passes, 3.00; 256K words, 2 passes, 2.00; 2.00M words, 2 passes, 2.00; 4.00M words, 1 pass, 1.00. Every answer was checked against a sort of the whole file.0123456784,09616K64K256K1.00M4.00Mmemory in 32-bit words, both buffers included (logarithmic)blocks moved ÷ blocks in the file4 passes3 passes2 passes1 passreread the file every passwrite the interval out everypasswrite it out when it hashalved4,194,304 keys, block 1,024 wordstwo passes from 256K words
Fig. 4 The same sweep on Pareto keys with equal-width cuts. Rereading: four passes and 4.00 up to 2,600 words, three and 3.00 to 64K words, two from 256K. Writing the interval out every pass: 7.64 at 2,100 words in six passes, 5.95 at 2,300, 4.26 at 4,096, 2.92 at 256K. Writing it out only when it has halved: 4.00, 4.00, 3.58, then within 7% of rereading everywhere.

Writing out on every pass is the worst policy here, by a wide margin. At 2,100 words it moves 7.64 files’ worth of blocks where rereading moves 4.00. The reason is in the counts. The first narrowing on these keys keeps 4,193,842 of the 4,194,304 — everything but 462, because 536 equal slices of a range up to 2302^{30} put almost the whole distribution into the first. A pass that then writes the interval out copies all 4,096 blocks to save reading none of them in the pass after. The next narrowing keeps 4,173,548 and the pass after that copies 4,076 blocks more, then 3,178, and only the fifth pass writes something small. The copying is paid in full every time and the saving comes at the end.

A second buffer makes it worse. On uniform keys, 24 pieces instead of 536 was harmless, because the interval was already small. Here the interval is still the whole distribution, and a pass that narrows 24 ways instead of 536 needs more passes to reach it. Writing out at every pass takes six passes at 2,100 words where rereading takes four.

The repair uses information the selector already has. Before a pass begins, the previous pass’s counts say exactly how many keys the interval holds, and the current file’s length is known. So the choice to write out can be made per pass, and the plate’s third line makes it the simplest way: write the interval out only when it is at most half the file being read. On uniform keys that fires on the second pass, where the interval is under two thousandths of the file, and the run costs 2.00 as before. On Pareto keys it holds off until the interval has actually shrunk. At 2,100 words it spills once, on the fourth pass, when the interval has fallen to 9,932 keys. The run costs 4.00, the same as rereading and half of writing out every time.

The rule is not optimal, and the plate says so. At 4,096 words it costs 3.20 where rereading costs 3.00. The interval had fallen to a fifth of the file, so the rule wrote those 820 blocks out — and the pass that wrote them narrowed straight onto the median’s value, so no pass ever read them. At 2,600 words the same bet paid: it wrote 1,193 blocks, read them once instead of the file once, and finished at 3.58 against 4.00. A rule that knew how many passes remained could do better on both, and the number of passes remaining is the one thing a narrowing selector cannot know in advance on data it has not seen. Half is a threshold that is never much worse than either choice. That kind of rule turns up again and again in these essays, and the writes nobody counted is the page where a threshold on writes first had to be priced rather than assumed.

The sampled cuts, priced as reads

The earlier essay’s repair for the heavy tail was to cut at order statistics of a sample rather than at equal widths. Each piece then holds the same count by construction, at the price of a pass: nobody knows the order statistics until a pass has gone by, so sampling and counting alternate. In the streaming model that price was a pass. On a file it is a read of the whole file, because the first sampling pass sees the whole file whatever the policy.

At 8,192 words the sampled cuts cost a whole extra read of the file on uniform keys and save one on Pareto keys; writing the interval out when it has halved changes neither by more than a few hundredthsBlocks moved divided by the file's 4,096 blocks, for exact selection of the median of 4,194,304 keys with 8,192 words of memory, equal-width against sampled cuts, rereading against writing the interval out when it has halved. uniform, equal-width: rereading 2.00 in 2 passes, writing out 2.00 in 2. uniform, sampled: rereading 3.00 in 3 passes, writing out 3.00 in 3. log-normal, equal-width: rereading 3.00 in 3 passes, writing out 3.00 in 3. log-normal, sampled: rereading 3.00 in 3 passes, writing out 3.00 in 3. Pareto, equal-width: rereading 3.00 in 3 passes, writing out 3.03 in 3. Pareto, sampled: rereading 2.00 in 2 passes, writing out 2.00 in 2.uniform, equal-width2.00 · 2 passes2.00uniform, sampled3.00 · 3 passes3.00log-normal, equal-width3.00 · 3 passes3.00log-normal, sampled3.00 · 3 passes3.00Pareto, equal-width3.00 · 3 passes3.03Pareto, sampled2.00 · 2 passes2.00reread every passwrite out when halved8,192 words, block 1,024reads of the file
Fig. 5 At 8,192 words, blocks moved divided by the file’s 4,096 blocks, equal-width against sampled cuts on three inputs. Uniform: 2.00 in two passes against 3.00 in three. Log-normal: 3.00 in three against 3.00 in three. Pareto: 3.00 in three against 2.00 in two. Writing the interval out when it has halved changes nothing by more than 0.03.

At 8,192 words the two rules trade places exactly as the earlier essay found for state. On uniform keys the sampling pass is an extra read of the file, 3.00 against 2.00, and it buys nothing that equal-width cuts did not already give. On Pareto keys the sample puts its cuts where the keys are. The first counting pass leaves only the median’s own value, and the run ends a whole pass sooner than equal widths do, 2.00 against 3.00. On log-normal keys, skewed but not extremely, they tie.

What changed is the unit, and the unit decides what a tie means. In the streaming model the comparison was between hundreds of bits and hundreds of thousands, a factor of eighty-three on the heavy tail. On a file both rules spend their state inside one block, so the state difference is invisible, and they differ only in how many whole reads they need: one pass more or one pass fewer. A choice that looked like two orders of magnitude in the streaming model is plus or minus a third on a file.

The Pareto keys also show the floor the earlier essay named for repeated values. They are rounded to integers, and 1,394 of them equal the median. Once the interval has narrowed to that one value, the counts already name the answer and no collecting pass is needed. The selector here takes that shortcut, and it is how every Pareto run above ends: the sampled one after its first count, the equal-width one after its third or fourth. The earlier essay did not take it, and paid for it in a flat row of 4,032-bit peaks.

What was measured and what was not

Transfers are counted and not timed. A block read and a block written are each one transfer. On a disk a write can cost more than a read. On flash it costs more and wears the device. And the writing-out policy interleaves reads of one file with writes of another, which on a single spinning disk is a seek per block unless both are buffered in larger runs. One access, eight kilobytes is the page on how much a block’s price depends on the device. Every conclusion above about writing out assumes a write costs about what a read does.

The block is 1,024 words and the file is 4,194,304 keys. The step from three passes to two sits where memory reaches about B+2nB + \sqrt{2n} — 3,920 words here — so a larger block moves it right by the block and a larger file moves it right by the square root. The law plate carries both, and the sweep was measured at one of each.

One rank, one file, one seed per input. The median of one draw of each distribution. Other ranks behave the same on uniform keys by symmetry. On Pareto keys a rank in the tail narrows more easily, because the tail is where the equal-width cuts have keys to separate, and it was not measured.

The spill rule’s threshold was not swept. Half was chosen before measuring, as the value that can never lose more than the cost of one wasted write of half a file, and the plate reports what it did rather than a threshold tuned to these inputs.

The streaming model is not wrong. It measures a different resource. On a wire there is no file, no second pass and no write, and the state law is the whole story — which is what the pass that was never a parameter set out from. The trade survives exactly where the file does not exist. A floor one pass cannot get under is a statement about that model and stays true. What this page adds is that a reader holding a file should read the law’s steep part as a statement about memory smaller than one page, and should ask a different question.

Still open: the counts a pass leaves behind

Every selection above starts from nothing. Its first pass reads the whole file and counts 536 or 1,534 pieces, and the run keeps only the one piece holding the rank it wants. The other counts are thrown away. They are a histogram of the whole file at the resolution the memory allowed, and they are exactly what a second query for a different rank would compute again in its own first pass.

The measurement that follows keeps them. It answers a sequence of selection queries against the same file — the median, then the 90th percentile, then the 10th, then a hundred ranks drawn at random — with the first pass’s counts retained between queries. Each later query then starts from its piece’s interval and needs one or two passes over the keys inside that piece rather than two over the file. With the pieces written out once, as a file partitioned by piece, a later query reads only its own piece. The question is how many queries it takes before writing the partition pays for itself, and whether the answer is set by the number of pieces, which is the memory, or by the number of queries, which is the workload. The prediction is that it pays by the second query on uniform keys and not until much later on a heavy tail, where equal-width pieces are one enormous piece and many empty ones. That would make the partition a place where the pass that runs the other way and this page meet: a pass whose value depends on what is asked after it.

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.

Block transferExternal-memoryHeavy tailHonest limitMeasurementModelMulti-passSamplingSelectionState bitsStreaming modelTrade off