40 comments

[ 3.1 ms ] story [ 105 ms ] thread
I'm usually a fan of Higham, but the last few posts have been weak.
(comment deleted)
Floating point operations per …?
Floating Point Operations Per Second [1]

[1] https://academickids.com/encyclopedia/index.php/FLOPS

> One should speak in the singular of a FLOPS and not of a FLOP, although the latter is frequently encountered. The final S stands for second and does not indicate a plural.

The author of this post seems to have fallen for this error.

I think their point was that the p stood for "per", not for the second letter of "operation".
FLOP = FLoating point OPeration, akin to the work that needs to be done (which could be measured in Joule)

FLOPS = FLoating point Operations Per Second, akin to the power of a given machine (which could be measured in Watt = Joule per second)

A task of W FLOP on a machine capable of P FLOPS will take T=W/P seconds. Or, a machine capable of executing a task of W FLOP in T seconds is capable of P=W/T FLOPS.

TL;DR: 1 FLOPS = 1 FLOP/sec

My personal notes on this subject:

* MIPS was perhaps the integer equivalent to FLOP, still used in modern microcontrollers because the 8051 at 12MHZ would only execute 1MIPS (12 clocks per instruction). Modern 8051 chips obviously have sped up to 1 clock per instruction, but MIPS (and Dhrystone MIPS in particular) are still a common benchmark today.

* FLOPs is very difficult to calculate in theory because modern CPUs have vector units, and multiple pipelines per core. You could have 3x AVX512 instructions in parallel on today's CPUs on a single core.

* FLOPs we're traditionally a 64-bit operation for the supercomputer community. Today, most FLOPs are 32-bit for video games. Finally, the deep learning / neural net guys have popularized 16-bit flops, and even 8-bit iops.

* 'The' flop is a misnomer because it's almost always the multiply-and-accumulate instruction: X = A + B * C. Which... Is two operations per instruction (per shader/SIMD lane). Eeehhh whatever. Who cares about these details?

* As 'Dhrystone' is the benchmark for MIPS, the benchmark for 64-bit flops is Linpack.

> 'The' flop is a misnomer because it's almost always the multiply-and-accumulate instruction: X = A + B * C. Which... Is two operations per instruction (per shader/SIMD lane). Eeehhh whatever. Who cares about these details?

If FMA is supported, it can either be counted as one or two operations, depending on the rule of the benchmark involved or the marketing of the processor. The marketing specification of a processor's theoretical peak performance sometimes counts a single-instruction FMA as two operations. On the other hand, for the purpose of code profiling, counting FMA as one operation is more realistic... As you said, who cares about these details?

Given that the point of the FLOPS unit is to compare processors, it does make more sense to count complex instructions as more than a single floating-point operation. If one CPU could multiply a 4x4 matrix by a vector in a single instruction that can run a million times per second, and another CPU needed ~32 instructions and so can only multiply 500k matrices per second but retires 16 million instructions in that same second, it would be silly to compare instructions instead of multiplications and additions.
As a computer-engineer, the circuit design needed to make a fast multiplication operation (ie: Wallace Tree, and similar) are an order-of-magnitude larger than the circuit design needed for fast addition (ie: a Kogge-Stone Carry lookahead Adder).

This idea that additions and multiplications can be combined like this as "equivalent operations" is kinda bullshit. But hey, if its "how its done" (and its done this way because multiply-then-add is how you do matrix-multiplications...) then so be it.

Just remember that this is an arbitrary subdivision of a matrix multiplication operation, that may not have much relevance as a benchmark outside of matrix multiplications.

It was just an example, not necessarily a realistic one. The point is that we want to compare how quickly a processor will compute our problem, not how many instructions it's going to execute. If it was a car you want to compare things like its top speed and acceleration, not something inane like engine revolutions per kilometer. You measure and compare things that are relevant to the user, not implementation details.
Okay, I think I see what you're saying now. I misinterpreted your statements earlier.
> not something inane like engine revolutions per kilometer

Unrelated to the thread but I just read that Top Fuel dragster engines only do about 240 revolutions over the 1000 foot race[1].

Never thought of it like that before so blew my mind a little.

[1]: https://en.wikipedia.org/wiki/Top_Fuel#Performance

FLOPS is a measure of throughput. The time-difference between a `fmul` and a `fmadd` is often in latency.

A modern processor is typically superscalar, with multiple individually pipelined floating point units that can each be issued one instruction per cycle: regardless of whether that is a `fmadd`, a `fadd or something else.

If you'd issue a `fmadd` to a unit, then you are prevented from issuing a `fadd` to it in that same cycle, and vice versa. That's one op, not two.

However, floating point units are sometimes heterogeneous. I think the question should be, rather: should you count the throughput of any ops, or of arbitrary ops. In other words, if a CPU runs at 1 MHz and has two units but where only one can run `fmul`, should you count the CPU as having one or two MFLOPS?

>In other words, if a CPU runs at 1 MHz and has two units but where only one can run `fmul`, should you count the CPU as having one or two MFLOPS?

I don't think there's enough information to answer that question. For starters, even if the CPU was issued a long sequence of nothing but additions, it's possible that it might spend some fraction of that million cycles waiting on memory.

I don't think FLOPS are counted from first principles, I think they're measured empirically using benchmarks. It's possible one benchmark will yield 1.25 MFLOPS and another 1.8 MFLOPS. Split the difference and call it a day.

> MIPS was perhaps the integer equivalent to FLOP, still used in modern microcontrollers because the 8051 at 12MHZ would only execute 1MIPS (12 clocks per instruction)

Actually the origin of this term was VAX MIPS (VAX 780 specifically) because that was a ubiquitous, pretty fast for its time minicomputer. There were faster machines, and slower mainframes still being built, but that was what the late 70s were like.

When the 8051 was released in 1980 it surely didn’t run at 12 MHz! Back then the Z80 sold because it could run 8080 code at a blistering 2 MHz.

BTW the benchmark for FLOPS in those days was Whetstone, hence the otherwise weird name “Dhrystone”

The 1981 manual for the 8051 contains numerous references to 12MHz.

http://bitsavers.informatik.uni-stuttgart.de/components/inte...

It was 12T clocked: even though the clock was 12MHz, it would only operate at 1MHz / 1MIPS, because it took 12-clock-ticks to even perform one addition.

IIRC, there was a standard crystal (11.0592 MHz crystal?? I forget exactly) for the communications at the time. So going just above 11 MHz (or really, just above 11.0592 MHz) was needed for reliable serial comms.

Wow, right on page 1-2! I'm surprised -- I don't remember anything running that fast back then. Thanks.

(Love those old Intel books too)

Nevertheless, FWIW, MIPS started out as Vax MIPS, and at first people often used to write "VAX MIPS".

8051 might run at 12 MHz, but actual instructions run in multiples of 12 clock cycles.

Realistic code on a 8051 runs only about 450k-800k instructions per second @12 MHz.

My last two startups.
You could use it as a unit of accounting for investing losses. A gigaflop would be a loss of 1 billion, etc.
Can somebody explain why a square root is also considered a flop? Surely that involves more work than the other four operations the article listed. Is there some hardware algorithm for the square root that is as fast as (e.g.) division?
Square root is pretty much equivalent to division in complexity, and computed by similar techniques (digit-by-digit methods or newton-raphson or goldschmidt iterations). Division is often a little more efficient, but square root has fewer messy edge cases (it never overflows nor underflows).

Division and square root are generally slower than the other arithmetic operations, in both latency and throughput. They are finally partially pipelined in recent CPUs (a result every two or three cycles), but were totally unpipelined in mainstream designs for many years before that. A decade ago, they might take a few tens of cycles, now they’re generally somewhere around ten cycles latency on “real” CPUs, vs 3-5 cycles latency for the other floating point arithmetic instructions.

Relevant Quake engine trivia, for those that are interested:

https://en.m.wikipedia.org/wiki/Fast_inverse_square_root

A question that I am not quite smart enough to figure out. The fast inverse square root works via a giant hack. hand waving a bit here but it has to do with because floats are stored as an exponential structure bit shifting one does magic math things to it. however note that bit shifting a float is not an implemented instruction. so you have to hack it by casting to an int.

Anyway the question is. If you implemented fast inverse square root with out the hack. (i don't know, perhaps packing your own bits, or it might be screwball enough you only assembly could do it.) would it be as fast?

It's not much of a "hack", it's literally how the number format works. If you implemented it without the "hack", you'd just be at the mercy of the compiler to see through your arithmetic on the float bit patterns and reconstitute it.

It's not actually that fast, either. Every mainstream architecture from the last 15 years (except maybe RISC-V, since it's exactly the sort of thing they would forget to add) has a "approximate square root" instruction with single-cycle throughput, and they're all both more accurate and more efficient than this. It was good for its time, but it's time has passed.

Guess: It's one of the operations specified in IEEE 754, and traditionally the implementation is supplied by your hardware vendor rather than implemented by you (even if that implementation is "really" a software algorithm).
There is no flop, it's flops even in the singular because it's an acronym.
A flop is something footballers do. flops are what CPUs do.
It was always an approximation to the real world computing need. a single instruction is how most people thought of flop or mips but it had to be a blend over the range of cost behind implementing a task, the ALU single thread/lock cost, and the problemspace.

If you do exclusively square roots over a giant matrix, being told the FLOP is based on a single 64 bit float division might not help you. (I cannot conceive of a problem solved only in square roots. This is a hyperbolic/reductive argument)

Given the distinction of single/parallel a lot of FLOPS stories and MIPS stories were somewhat mythic anyway. Then manufacturers started gaming the test suites.. it was always very notional.

I ask, if IOPS is in fact any better? or SQL transaction models? I might be stuck in a problem which is a LEFT OUTER JOIN do I not need to know that cost distinct from a well optimised single B Tree index cost?

I worked on an 11/780. Many in fact, both as an operator and as a user. It was awesome. But, I reminded myself the Dec-10 alongside had happily been supporting 70-80 users in parallel, running MUD, being a sort-of mainframe, I had no conscious sense of how "big" an IBM 360 was by comparison. A Vax 11/780 was however, really quite fast at processing the same FORTRAN jobs which ran on the Dec-10. The Dec-10 had a floating-point systems "ice cream cabinet" glued on the side as an array processor. It ran tasks compiled to run on it very very fast but that was a narrow problemspace. This was 1982-3.

How many flops for a full qcd atomistic simulation of a human in real time?