4 ms·
> Avoid complex operations, which may include things such as multiply and divide. How can this possibly make sense? Almost every application multiplies and div
by qwerty456127 6y ago
> Avoid complex operations, which may include things such as multiply and divide.
How can this possibly make sense? Almost every application multiplies and divides all the time anyway. It usually is a good idea to implement frequently used operations in hardware because hardware implementation is always more efficient than software implementation, isn't it?
- Asooka 6y agoThat was for back when CPUs didn't really have native division or multiplication. So a mul or div would literally be like calling a function to do it using other arithmetic instructions, except the function is stored in the CPU. Which goes against the RISC philosophy and makes the CPU more complex for not much gain.
- qwerty456127 6y ago> So a mul or div would literally be like calling a function to do it using other arithmetic instructions, except the function is stored in the CPU. Wouldn't this be times (if not orders of magnitude) faster than loading it in software anyway? I believe it was one of the most frequently used functions, hard or soft.
- undersuit 6y ago>I believe it was one of the most frequently used functions, hard or soft. Left Shift and Right Shift are extremely hurt by this comment.
- marcan_42 6y agoMultiplication is reasonably common. Once you have multiplication by a constant you get division by a constant for free, so that leaves division by a variable. That is a very rare operation in non-mathy code, and usually for math you'd end up with floating point division anyway which is a whole different ball game (good code anyway; people writing for modern CPUs will of course throw integer division and modulo around without second thought, but the vast majority of the time you can avoid those operations and run faster).
- aidenn0 6y agoMany of the "true RISC" cpus that could dispatch 1 ALU instruction per clock cycle had instructions for accelerating division; it would do one round of division and could be called in a loop to implement a full divide. Note that dividing by a constant does not need a divide instruction, so it's only when dividing by a variable that division is needed. Even on CISC machines of the time division instructions were so slow that programmers would go out of their way to avoid using them.
- wk_end 6y agoEven in hardware, multiplication and division are much slower than addition or subtraction. The speed you can run your processor at is bound by the slowest thing in your data path. So if you want a native division instruction, either you slow the CPU down so that a division can execute in a single cycle or you make the instruction run over the course of multiple cycles, complicating your pipeline. The original RISC guys were dogmatic (or, more generously, they were researchers exploring the possibilities of an idiosyncratic dogma), and their dogma dictated that: 1. a simple - and fully exposed - pipeline could be more fully exploited by programmers and compilers and served as a better use of chip real estate, so everything should run in a single cycle 2. keeping your data path simple so that you could ramp up the clock speed was the key to overall speed So they chose to scrap multiplication and division altogether. In practice, much of this probably turned out to be a bad idea, at least as chip technology has improved (and memory speed relatively stagnated), and that brings us to today.
- marcan_42 6y agoDivision is still optional in ARM; their smallest core (Cortex-M0) does not have it. That makes perfect sense for that class of embedded core; to be honest, division by a variable is a very rare operation in embedded code (division by a constant is multiplication by the reciprocal, so that doesn't need a division instruction).
- fulafel 6y ago> Almost every application multiplies and divides all the time anyway This is the crux of the RISC philosophy: Most things happen "all the time" in processors since they do a lot of things very fast, but what really matters is how often. The quantitative approach is actually looking at what instruction mix and its fastest implementation given to a reasonably competent compiler prouduces fastests overall results (given that simpler chips could be clocked faster, have shorter pipelines so better branching, leave more space for cache, etc). The thing about multiplicationsan divisions, besides being slow in silicon, is that you can actually cover a surprisingly big part of application code multiplies with just a couple of shifts and adds. This is especially true for constant multiply or a known smallish range of multipliers, which optimizers are good at discovering. But of course the transistor budgets and tradeoffs were different in the days of early RISC. Still, even the relatively recent RISC-V elided multiply and divide from the base instruction set.