8 ms·
The Pentium contains a complicated circuit to multiply by three
- kens 2y agoAuthor here if anyone has questions...
- java-man 2y agoKen, maybe it's time to publish a book?
- kens 2y agoThat would require me to focus on one subject :-)
- JohnKemeny 2y agoThen publish many books?
- ForOldHack 2y agoI ancient times, it would be nice to curl up to a nice scroll ,later on a nice bound book, now we are selecting the background colors on our e-readers. These articles are hard-core good. I would like to hear much more about the R4200i than the 286.
- java-man 2y agoHere is an example: a certain blogger, Dave Addey [0] published a book [1] which is basically a hardcopy of the blog. After the EMP flash of 2075, the centient raccoons will enjoy reading the stories of the civilization long gone. [0] https://typesetinthefuture.com/author/typesetinthefuture/ https://typesetinthefuture.com/author/typesetinthefuture/ [1] https://www.amazon.com/Typeset-Future-Typography-Science-Fiction/dp/1419727141 https://www.amazon.com/Typeset-Future-Typography-Science-Fic...
- fargle 2y ago*sentient raccoons (we are pedantic)
- ForOldHack 2y agoI have to respect his choice to focus on the 8086 and the pentium, I would think he considers the 80286 a brain dead footnote, interesting as to what when wrong and what went terribly wrong. I used to teach binary math to kids, and at a county fair I was upstaged by an 11 year old girl who demonstrated both multiplication by powers of two and division of powers of two. "What does your father do for a living?' "He is the director of the laser fusion project!" "Oh."
- kristianp 2y agoThe 286 could process twice as many instructions per clock as an 8086. According to Wikipedia, an uplift similar to the 80486 and the Pentium over their predecessors.
- ForOldHack 2y agoSo that is wikipedias "opinion" which any one could edit. I should edit that to reflect where the performance came from. Always check sources. ( The reference comes from intel386. com)
- ForOldHack 2y agoThe cited website went offline this morning, and it does not discuss the execution rate of the 286, NOR does it discuss the reserved bytes in the GDT, and LDTs. Not a lot of confirmation.... https://web.archive.org/web/20160204052256/http://intel80386.com/386htm/s13_02.htm https://web.archive.org/web/20160204052256/http://intel80386... " For those descriptors that are common to both the 80286 and the 80386, the presence of zeros in the final word causes the 80386 to interpret these descriptors exactly as 80286 does; for example: " This is patently and documented as untrue. The final word is reserved for use as a 365 GDT, and breaks 286 code, specifically Xenix 286, on a 386. https://www.os2museum.com/wp/theres-more-to-the-286-xenix-story/ https://www.os2museum.com/wp/theres-more-to-the-286-xenix-st...
- dsvf 2y agoNo question, but just in general appreciation for the wonderful content you put out there that we get to enjoy!
- vanderZwan 2y agoWhat happened to the dedicated "times three" multiplier in later machines? Did some form of it stick around? Did they change tactics to something making it obsolete?
- kens 2y agoThere were a lot of different algorithms in use back then. I don't know if there is a winner used in modern chips.
- phire 2y agoObsolete. You can observe the evolution of multipliers in the MIPS line, which I've been studying, and happen to know. The R3000A had the same Radix-8 (aka 3-bit per cycle) integer multiplier in 1989. The R4000 had two Radix-8 multipliers in 1991. One for integer, one for floating point. The R4400 was an upgraded R4000 in 1992. The integer multiplier was kept at Radix-8, but the FPU was upgraded to a Radix-256 design (aka 8-bits per cycle). In parallel, MIPS spent a lot of time creating a low power design for the target market of "Windows NT laptops". The result was the R4200, released in 1993. MIPS published quite a bit of information about the various power saving optimisations [1], [2]. Instead of seperate integer and floating point data paths, they created a unified data path that did both, allowing them to use the same Radix-8 multiplier for everything. They even unified the multiplier unit into the main adder, rather than using a seperate adder like earlier designs. In 1995, MIPS released the R4300i, (aka the CPU found in the Nintendo 64). It was an evolution of the r4200, keeping the unified float/integer datapath. But it gained the Radix-256 multiplier from the R4400 design, so both integer and float instructions complete at 8-bits per cycle. As far as I can tell, this Radix-256 multiplier doesn't use any fancy tricks. It's just an array of eight 64-bit wide carry-save adders, feeding into a regular carry-lookahead adder. In 1996, MIPS released the R10000. Transistors are now cheap enough that they could implement a full 52-bit adder for their floating point data path, allowing them to issue one double precision multiplication every cycle (though it's pipelined with a 2 cycle latency). I assumes it's just 52 stacked adders, though seems like they probably need to be doing something fancier with carries by the time it's that big. Most modern CPUs have ended up at the same point. Massive pipelined arrays of adders that can execute one 64-bit multiplication every cycle, with a 3 cycle latency. [1] https://www.youtube.com/watch?v=nll5MWlG7q4 https://www.youtube.com/watch?v=nll5MWlG7q4 [2] https://ieeexplore.ieee.org/document/282948/ https://ieeexplore.ieee.org/document/282948/
- dwedge 2y agoI only tenuously understand this so feel free to ignore the question if it's too asinine but: > (What about ×5? If you can compute ×3, you can subtract that from ×8 to get ×5.) Why can't you do the same to subtract x4 from x7 to get x3?
- mikequinlan 2y agox7 is computed by x8 - x, so you get x8 - x - x4 which is 2 subtractions (and 2 delays). You only want 1 delay.
- thombat 2y agoBecause x8 is simply shifting 3 bits left so it's "free" (fixed-sized shifts are very simple to implement), whereas generating the x7 would require the additional circuitry, which additionally will be more expensive than the x3 was (since it's another shift+add beyond what x3 required)
- russdill 2y agoThe question would be why isn't it 4x - 1x?
- kens 2y agoThe trick is that Booth's algorithm gives you the ×8 term for free; you multiply by one more in the next base-8 digit. You can put either ×4 or -×1 into a term, but you can't put both of them into one term. So you can do ×8 - ×1 but you can't do ×4 - ×1.
- eru 2y agoI guess the decimal equivalent would be multiplying by 10 vs multiplying by 5. Or for hexadecimal: multiplying by 0x10 (16) or by 2, 4 or 8.
- mjevans 2y agoI suspect it's logically equivalent, but one bit wider in hardware. Binary 4x is left shift by 2, rather than 2x which is by one. Adding or subtracting in 2's compliment space is the same operation for the bits of the word.
- kristianp 2y agoThis is probably a basic question, but is this for floating point multiplies? Isn't the part thats being multiplied less than 64 bits because you also add the exponents?
- kens 2y agoYes, this is for floating point multiplies. But internally, the FPU uses x86 extended-precision numbers, 80-bit floats, with 64 bits of significand and 15 exponent bits. So the multiplier is dealing with 64-bit numbers, plus a few more bits to support rounding correctly. https://en.wikipedia.org/wiki/Extended_precision#x86_extended-precision_format https://en.wikipedia.org/wiki/Extended_precision#x86_extende...
- rob74 2y agoNot really a question, just one phrase that left me scratching my head a bit: > The downside to radix-8 multiplication is that multiplying by a number from 0 to 7 is much more complicated than multiplying by 0 or 1, which is almost trivial. I think you can leave out the "almost" there - multiplying by 0 is 0 and multiplying by 1 is the number itself, as shown in the example, so I would definitely call it trivial.
- artemonster 2y agoTLDR: 3a = (a << 1) + a
- vanderZwan 2y agoFrom the article: > Multiplying a number by three is straightforward in binary: add the number to itself, shifted to the left one position. (As mentioned above, shifting to the left is the same as multiplying by two and is easy in hardware.) Unfortunately, using a simple adder is too slow. So no, not really. In fact the entire point of article is arguably explaining why it is not that simple.
- mjevans 2y ago"This ×3 multiplier contains roughly 9000 transistors, a bit more than an entire Z80 microprocessor (1976). Keep in mind that the ×3 multiplier is a small part of the floating-point multiplier, which is part of the floating-point unit in the Pentium. Thus, this small piece of a feature is more complicated than an entire microprocessor from 17 years earlier, illustrating the incredible growth in processor complexity." That's the pace of performance growth that lead software to become bloated today; next year's performance improvements would cover up most of the sins of failure to think critically about algorithms and data flow context / locality. Today (as far as I've read) we're at the practical limit for what's reasonable to do with silicon semiconductor technology and our present understanding of physics. The pendulum needs to swing the other direction; it's time for computers to work smarter not harder.
- HPsquared 2y agoLuckily there is plenty room for improvement in most applications.
- ajsnigrutin 2y agoBut why would we waste thousands of hours of programmers time to optimize stuff, if we can instead waste millions if not billions of hours of users' time? /s
- dijit 2y agoyou know it’s funny, the first time I ever read a book about compiled languages- I think it might have even been K&R C… it talked about the fact that code is run significantly more often than it’s compiled, and read more often than it’s written. Thus we should optimise for runtime speed and afterwards readability. Yet on hacker news, the exact opposite sentiment is true. Employee hours are expensive, so optimise as much as you possibly can and push as much time onto the user as they will tolerate. Focus primarily on readability to the detriment of all other factors. Heck, even don’t bother compiling your program. Use an interpreter on the server. Keep your local cost down, your remote cost up… after all remote cost are not your cost, especially if every company is doing the same thing. It’s ironic that I could read a book and it be so wrong, yet that book is the foundation Bible for many people’s programming journey.
- sifar 2y agoInteresting choice of radix-8 booth multiplier that needs the x3 circuit. Seems like a area/perf tradeoff in order to push the fmax which means they had a latency cycles constraint since the same could be achieved via more pipelining.
- kens 2y agoYes, it's a tradeoff. Many other FPUs at the time used radix-4 instead because it avoids the extra ×3 circuit. Pipelining is tricky because there isn't a nice place to break the multiplication array into two pieces.
- sifar 2y agoSure it takes a few iterations, but there is nothing inherently complex about it. You feed the partial products into a carry-save adder tree and choose a level which minimizes the delay and the extra flop area/power. I am not sure about the pentium technology but whatever the area, it might be comparable to the x3 multiplier There is an implicit add in the x3 multiplier circuit that increases the delay which was deemed acceptable than the radix-4 delay. Considering all this, I strongly believe latency was a hard constraint (may be for SW perf).
- efitz 2y agoA long time ago on the 6502 I was trying to figure out how to quickly multiply by 3 in assembly and I came up with: 1. Shift-left 2. Add original value For multibyte values use rotate left which carries, and do the rotates from LSB to MSB. Then clear carry, then do the adds from LSB to MSB with carries. Should work for any word size. Ofc I was a teenager but this seemed clever and simple to me. Was (am) I just missing something?
- bean-weevil 2y agoThis is covered in the article. See the section "Implementing a fast ×3 circuit with carry lookahead"
- efitz 2y agoThank you. I stopped reading after the octal discussion.
- russdill 2y agoFor most assembly, I'm not sure how this has an advantage over two adds.
- jonsen 2y agoA shift is faster than an add.
- brcmthrowaway 2y agoCan AI come up with this circuit?
- goldfishgold 2y agoAlmost certainly, insofar as it’s already known and described in a number of places, including Wikipedia.
- eru 2y agoThough it would be interesting to run an experiment where you somehow remove all of that from the training data. Perhaps in 10 years training runs will be cheap enough, that one a whim you could just train a new AI model on data from only before the Pentium was released, and then see if it could come up with it?
- thaumasiotes 2y agoI'm missing something: > The downside to radix-8 multiplication is that multiplying by a number from 0 to 7 is much more complicated than multiplying by 0 or 1, which is almost trivial. Fortunately, there are some shortcuts. Note that multiplying by 2 is the same as shifting the number to the left by 1 bit position, which is very easy in hardware—you wire each bit one position to the left. Similarly, to multiply by 4, shift the multiplicand two bit positions to the left. > Multiplying by 7 seems inconvenient, but there is a trick, known as Booth's multiplication algorithm. Instead of multiplying by 7, you add 8 times the number and subtract the number, ending up with 7 times the number. You might think this requires two steps, but the trick is to multiply by one more in the digit to the left, so you get the factor of 8 without an additional step. > Thus, you can get the ×7 by subtracting. Similarly, for a ×6 term, you can subtract a ×2 multiple and add ×8 in the next digit. > Thus, the only difficult multiple is ×3. (What about ×5? If you can compute ×3, you can subtract that from ×8 to get ×5.) If we can easily compute ×2 for the purposes of exploiting 6x = 8x - 2x, and we can easily compute ×4 for the purposes of exploiting 4x = 4x... why is it more difficult than that to compute 3x as the sum of 2x and 1x, or the difference of 4x and 1x? Also, if we can easily compute ×6 by any means, why not compute ×3 as a right shift of that value? That is admittedly an extra step, but the extra step is a shift.
- kens 2y agoFor the 64-bit multiplication, you're adding 22 terms, one for each base-8 digit. (Think of grade-school multiplication.) Each term needs to be trivial to compute, so you can do a shift and/or a negation to get the term, but you can't do another addition. The point is that ×3 is precomputed once, so you can then simply feed it into any of the 22 terms as needed. You can't do ×2 and ×1 into a term to get ×3 because every term would need another adder. In other words, you want one circuit to compute ×3 rather than 22 circuits. For your ×6 question, this value is computed by putting negative ×2 into the term and conceptually adding one more to the next digit to get ×8. You can't right-shift this ×8 value since it's part of a completely different term. Hopefully this makes sense. There are a lot of digits and sums flying around.
- thaumasiotes 2y ago
- marginalia_nu 2y agoThis is a very tangential. I did some work in Trinary computer emulation a lifetime ago, there's a cute trick for finding a closed form translation between a division by a power of 3, and series of bit shifts and additions. Start by observing that 1/3 - 1/2 = 2/6 - 3/6 or 1/3 = 1/2 - 1/2 (1/3) Substitute equation above into RHS an infinite number of times and find 1/3 = -(-1/2)^N for N in 1..inf You can do this with arbitrary pairs powers of 2 and 3 (also other bases). The implication is that you can fairly easily build a fixed time divide-by-constant circuit as out of nothing but adders and subtractors for values that are close to a power of two.
- ngneer 2y agoIncredible, thanks for sharing. My understanding is that ternary computers would have been based on tri-state logic which was less reliable than say transistors or even vacuum tubes encoding binary state. Is that understanding correct?
- initramfs 2y agohttps://github.com/EI2030/Low-power-E-Paper-OS/blob/master/PMOS%20Scaling.png https://github.com/EI2030/Low-power-E-Paper-OS/blob/master/P... 8086: 29,000 386: 275,000 486: 1.2 million Pentium: 3.1 million The NSA entered the game sometime after 2000, I recall.
- phkahler 2y agoThe Cinematronics arcade game processor has two 12-bit accumulators. The multiply instruction shifts them right as a single 24-bit value and adds the contents of memory if a 1 came out the LSB. So you clear the upper half, load one value in the lower, I forget how you set the memory address for the other operand... and execute several 1-bit multiplies is a row. You can get a 24bit product this way, but most code I saw had runs of 8 multiplies. The most common thing was a 2x2 matrix multiple to do coordinate rotations for game objects. This was in the mid 1970s using off the shelf 7400 series parts and had peak throughput of 5MIPS.
- greesil 2y agoNot exactly one cycle for a multiply it sounds like. That 5 mips would be eaten up quickly. I have sometimes had to do fixed point math in the past 20 years and have had much respect for those programmers who came before me.
- phkahler 2y ago>> Not exactly one cycle for a multiply it sounds like. That 5 mips would be eaten up quickly. Sure taking 8 instructions for a multiply is a lot, but microprocessors at that time didn't even have multiply and ran below 1MIPS. I just wanted to bring it up as yet another way someone implemented multiply, and it was pretty effective for its time. EDIT: too late to edit my original comment, but it added the memory value to the upper half of the 24-bit result.
- greesil 2y agoAside from a really weird 8051 project in the aughts I've only ever had single cycle multiplies.
- philsnow 2y ago> you may have heard of techniques such as carry lookahead, Kogge-Stone addition Just an aside, that is Peter Kogge, who did his PhD work at Stanford, worked on the space shuttle, is an IBM fellow, and invented the first multi-core cpu.
- atq2119 2y ago> invented the first multi-core cpu The man clearly has many deserved achievements to his name, but that is true without this, and I'm confident the world would be better without this kind of statement. "A multi-core CPU" isn't much of an invention per se. It's an idea -- one that is fairly obvious and trivial at a certain point of semiconductor history. Getting a multi-core CPU to run is not trivial, but it's not a single invention either, and by the time we got there, development teams were so large that it would be downright insulting to claim that one person solved all these problems by himself. Perhaps Kogge led the development of the first multi-core CPU, perhaps he was even visionary in the sense that he pushed for it before others thought it was feasible (I do not know if that is the case). But either way, he didn't invent it.
- philsnow 2y agoThank you for keeping me honest, I concede the point; I was quoting from his Wikipedia entry and wasn’t particularly critical because I took an architecture class from him in grad school and liked him as a professor.
- reaperman 2y agoThis raises my general curiosity to ask myself: among the set of things that could be said to have been truly invented by a single person (or pair/trio/tiny team) ... which inventions are the most complex ... and which are the most technologically advanced?
- oidar 2y agoI thought Kunle Olukotun led the team for the first multi-core CPU.
- lewdwig 2y agoMultiplication by 3 is actually a common operation, particularly in address calculations, where a shift and an add means multiplying the index by 3. Implementing this naively would add significant latency. But using this circuitry the LEA (Load Effective Address) instruction can do it in a single cycle, so spending this much transistor budget on it was totally a good call.
- quadhome 2y agoIs it used for that, though? As I understood the article, this circuit is used as a part of floating-point multiplication.
- kazinator 2y agoWhat? - LEA is just an instruction moves the address calculated by an addressing mode into its output operand, rather than performing a data transfer to or from that address; all the addressing that LEA can do, MOV instructions can also do. - The indexed addressing modes of the x86 used by MOV or LEA do not support a scale factor of 3, only powers of two: 1, 2, 4, 8. So address generation has no use for multiplication by 3. - Article makes it clear that the multiplier by 3 is part of the floating point multiplier.
- phkahler 2y ago>> Instead of multiplying by 7, you add 8 times the number and subtract the number, ending up with 7 times the number. You might think this requires two steps, but the trick is to multiply by one more in the digit to the left, so you get the factor of 8 without an additional step. Does this mean there's an "adder" to add 1 to the "next digit" prior to feeding the digits to the main part of the multiplier? That itself seem like it'd be similar to the carry lookahead circuit. Also thinking about when that needs to be done: 7 = 8-1 6 = 8-2 5 = 8-3 4 = 8-4 <- he didn't say they do this, but it would mean the MSB of the 3-bit value could be used to determine if we need to add 1 to the next digit, saving a couple gates.