Wow, you're absolutely right. I should have said that is no SIMD instruction for integer division (which is what I needed for the ranged random numbers), and somehow I got the idea that they didn't exist for floating point either. The 64-bit division timing I quoted was after looking at IDIV on Haswell:
IDIV | r64 | 59 | 59 | p0p1p5 p6 | 39-103 | 24-81
http://www.agner.org/optimize/instruction_tables.pdfThis is saying that it takes 59 µops spread across Ports 0, 1, 5, and 6 to a signed integer division. That latency for a single operation will be between 39 and 103, but if you are doing many signed integer divisions in a row you'll finish a division once every 24 to 81 cycles.
For DIVPD on Haswell we have:
VDIVPD | y,y,y | 3 | 3 | 2p0 p15 | 19-35 | 16-28
Here it takes only 3 µops (2 on Port 0, one on Port 1 or 5), has a single instruction latency of 19 to 35 cycles, and if doing many in a row we can finish one vector's worth of divisions every 16 to 28 cycles. Since a 256-bit YMM register holds 4 doubles, this is about 6 cycles per double precision division.
Performance on Skylake is dramatically improved:
VDIVPD | y,y,y | 1 | 1 | p0 | 13-14 | 8
Only one µop (on Port 0), a latency of 13-14 cycles, and an inverse throughput of just 8 cycles. Thus the best case double precision requires only 2 cycles per division!
By contrast, double precision addition on Skylake is 1 µop on Port 0 or Port 1, 4 cycles of latency, and optimally we can complete 2 of these operations per cycle (inverse throughput of .5). At 4 doubles per YMM vector, this means we can do 8 double precision additions per cycle, or 16 every two cycles.
So on the most recent Intel processors, in the best optimized case, double precision division should be 16 times slower than double precision addition --- much closer to your 10x estimate than my 100x. I think my numbers are still about right for 64-bit integer division, but I appreciate the pushback.