Live data from Hacker News

Implementing Cosine in C from Scratch (2020)

austinhenley.com

81–90 of 139 posts

Re: Implementing Cosine in C from Scratch (2020)

#81
post #59
post #15

Earlier quoted context omitted.

https://github.com/ifduyue/musl/blob/master/src/math/__cos.c

I think the polynomial calculation in the end looks interesting. It doesn't use Horner's rule.

It does use Horner's rule, but splits the expression into two halves in order to exploit instruction-level parallelism.

Re: Implementing Cosine in C from Scratch (2020)

#83

Earlier quoted context omitted.

No. The fsin instruction is inaccurate enough to be useless. It gives 0 correct digits when the output is close to 0.

> 0 correct digits when the output is close to 0 this is an amusing way to describe the precision of sub-normal floating point numbers

It's not just sub-normal numbers. As https://randomascii.wordpress.com/2014/10/09/intel-underesti... shows, fsin only uses 66 bits of pi, which means you have roughly no precision whenever abs(sin(x))<10^-16 which is way bigger than the biggest subnormal (10^-307 or so)

Re: Implementing Cosine in C from Scratch (2020)

#84
post #74

Earlier quoted context omitted.

The question is if you wouldn't be better served with double-doubles today. You get ~100 bits of mantissa AND you can still vectorize your computations.

Sure. There should be a gcc flag to make "long double" become quadruple precision. The thing is, my first programming language was x86 assembler and the fpu was the funniest part. Spent weeks as a teenager writing almost pure 8087 code. I have a lot of emotional investment in that tiny rolling stack of extended precision floats.

How is "quad floating point" implemented on x86? Is it software emulation?

Re: Implementing Cosine in C from Scratch (2020)

#85
post #63

Earlier quoted context omitted.

How long does the cache thrashing loop take compared to 500 iterations? I'm not sure how much you can trash the cache while still being performance bottle-necked by a table-based implementation of a trig function.

Yes of course the cache thrashing takes a lot longer. But I modified the code to time only the cos() functions (see diff), using the rdtsc instruction. That's why it had to be every 500 iterations: If it was after each iteration, then rdtsc itself would become the bottleneck!

My point wasn't about how you were timing the code, what I meant is in the real world, I don't think there are programs where this will be an issue because if they are thrashing their caches too much, they won't be bottlenecked on trig. The advantage of table based functions is that they are really fast if you are calling a lot of them at once, but that's also the only case where they need to be fast. If only 1/10000 instructions is trig, it's OK if the trig is a little slower.

Re: Implementing Cosine in C from Scratch (2020)

#86

Earlier quoted context omitted.

> I guess on intel architectures the compiler just calls the fsin instruction of the cpu. Do people do that in practice? It's on the FPU, which is basically legacy emulated these days, and it's inaccurate.

> the FPU, which is basically legacy you'll pry my long doubles from my cold, dead hands!

You're selectively quoting me - I said it's 'legacy emulated'. It's emulated using very long-form microcode, so basically emulated in software. I didn't say it was simply 'legacy'.

Re: Implementing Cosine in C from Scratch (2020)

#87
post #69

Earlier quoted context omitted.

FSIN only works on x87 registers which you will rarely use on AMD64 systems -- you really want to use at least scalar SSE2 today (since that is whence you receive your inputs as per typical AMD64 calling conventions anyway). Moving data from SSE registers to the FP stack just to calculate FSIN and then moving it back to SSE will probably kill your performance even if your FSIN implementation is good. If you're vector…

Moving between x87 and xmm registers is actually fairly cheap (it's through memory, so it's not free, but it's also not _that_ bad). FSIN itself is catastrophically slow.

[deleted]

Re: Implementing Cosine in C from Scratch (2020)

#88
post #69

Earlier quoted context omitted.

FSIN only works on x87 registers which you will rarely use on AMD64 systems -- you really want to use at least scalar SSE2 today (since that is whence you receive your inputs as per typical AMD64 calling conventions anyway). Moving data from SSE registers to the FP stack just to calculate FSIN and then moving it back to SSE will probably kill your performance even if your FSIN implementation is good. If you're vector…

Moving between x87 and xmm registers is actually fairly cheap (it's through memory, so it's not free, but it's also not _that_ bad). FSIN itself is catastrophically slow.

Fair enough, and I imagine there may even be some forwarding going on? There often is when a load follows a store, if I remember correctly. (Of course this will be microarchitecture-dependent.)

Re: Implementing Cosine in C from Scratch (2020)

#89
> So we are really only calculating cosine from 0 to pi.

You could go further and only to 0 to pi/2 as it is mirrored and flipped for pi/2 to pi.

Or you could go even further and do only 0 to pi/4 and use a simple trig identity and your presumably parallely-developed sin function for the cos of pi/4 to pi.

> One of the implementations is nearly 3x faster than math.h

Is this true even for -O3?

Re: Implementing Cosine in C from Scratch (2020)

#90
post #59

Earlier quoted context omitted.

I think the polynomial calculation in the end looks interesting. It doesn't use Horner's rule.

It does use Horner's rule, but splits the expression into two halves in order to exploit instruction-level parallelism.

Considering the form of both halves is the same, are compilers smart enough to vectorize this code?
Post reply on HN