I am very familiar with such low level workings. On a modern, fast machine, the amount of computation required by FM synthesis is so small compared with the machine's throughput that it just doesn't matter.
Yes, on modern chips float math will generally be faster than fixed point. This is not so much because the integer units get clogged, as that there's a huge amount of chip area and optimization that goes into the float units (often SIMD, and a lot of FM synthesis can benefit from this, though feedback creates data dependencies). For example, multiply-and-add is usually one cycle in float, but would always be two separate instructions in integers.
My recollection is that older ARM chips have a special issue with latency of data dependencies originating from the float unit (NEON, which is optimized for SIMD vector operations) to the integer unit. I suspect this is no longer the case, or is less of an issue.
Historically yes. This is most definitely not true since processors had SSE3 (~2004), using the FISTTP instruction, or I think you can also use the packed float to integer instructions like CVTTPS2PI as far back as SSE (1999).
Cheers for the explanation. I suppose "modern" should be asterisked, since I was parroting posts that date back to the mid-00s. Things have probably changed considerably from then.
I'm specifically targeting an Intel Atom, which is obviously powerful enough for the task, but may not fit all definitions of "modern" now?
Got me curious regarding ARM latency, wonder if that was related to particular instructions which added more latency or transfers between the registers/memory subsystem internals. Also on the off-chance that you remember, did you inline intrinsics or let the compiler auto-optimize?
Interesting to test out on the ARM Mac, and see if different dependency chains show significant latency penalties / in with reorder buffer.
This is for Cortex A8, which was the chip in the Nexus One. I wrote the original version of sound synthesis directly in ARM assembler[1]. It was very highly optimized, I remember using a cycle counting app that flagged any dependency chain that would cause the processor to stall, and ultimately utilization was in the 90%+ range. Back in those days, processors were simple enough you could do this kind of optimization by hand. By the time of Cortex A15 (Nexus 10 etc), instruction issue was out-of-order and much harder to reason about.
The best current info I could find for the latency advice is [2]. Quoting, "Moving data from NEON to ARM registers is Cortex-A8 is expensive." Looking at [3] partially reveals the reason why: the NEON pipeline is entirely after the integer pipeline, so moves from integer to NEON are cheap, but the reverse direction is potentially a large pipeline stall. This is an unusual design decision that as far as I know is not true for any other CPUs. Edit: I found [4], which is a more authoritative source.
Awesome reply, and thank you for the well put together answer linking to resources and for sharing your experience.
For Cortex-A8 from [4] and the others you have linked, It makes sense to me now regarding the instruction passing data between registers, filling out the pipeline and then stalling.
Will have a peek at ARMv8/ARMv9 arch's and see what they did there regarding SVE/SVE2.
Yes, on modern chips float math will generally be faster than fixed point. This is not so much because the integer units get clogged, as that there's a huge amount of chip area and optimization that goes into the float units (often SIMD, and a lot of FM synthesis can benefit from this, though feedback creates data dependencies). For example, multiply-and-add is usually one cycle in float, but would always be two separate instructions in integers.
My recollection is that older ARM chips have a special issue with latency of data dependencies originating from the float unit (NEON, which is optimized for SIMD vector operations) to the integer unit. I suspect this is no longer the case, or is less of an issue.