3 ms·
Author here. > I'm surprised it doesn't eliminate the BenchmarkAtan2 entirely: I'm sorry, could you clarify what you mean by "eliminate" here. Are you saying
by agnivade 9y ago
Author here.
> I'm surprised it doesn't eliminate the BenchmarkAtan2 entirely:
I'm sorry, could you clarify what you mean by "eliminate" here. Are you saying I shouldn't benchmark atan2 but something else ?
> Are you sure you're compiling with optimizations enabled?
I just did - `go test -bench=. -benchmem -cpu=1`. Did I miss something ?
> I also wonder if that DIVSD instruction in yours might cause a floating point exception, which would be a different behavior compared to atan2.
I checked with the assembly output of math.Atan2. It also uses DIVSD.
- sbierwagen 9y ago>could you clarify what you mean by "eliminate" here. He's talking about a common compiler optimization: https://en.wikipedia.org/wiki/Dead_code_elimination https://en.wikipedia.org/wiki/Dead_code_elimination Some compilers are smart enough to not run code that doesn't have any side effects. (Running a function a million times in a row but never doing anything with the results) Hopefully golang bench is smart enough to not be that smart.
- agnivade 9y agoGot it. Thanks ! > Hopefully golang bench is smart enough to not be that smart. Yes, that seems to be true.
- conistonwater 9y agoI don't know about go specifically, but in general if a compiler sees that the result of an expression is thrown away (like here: you don't use it anywhere), and there are no side effects to the expression, then it's okay to replace it with a noop. Usually it's better to write benchmarks in a way that the result of the mathematical expressions is used, like if you kept a running sum of `atan2(rand(), rand())` and then printed it.
- munificent 9y ago> I'm sorry, could you clarify what you mean by "eliminate" here. Most compilers will eliminate code if they can tell the results of a calculation are never used. Benchmarks typically call some function and discard the result. If you aren't careful, the compiler can often optimize away your entire benchmark down to nothing. This is why you often see benchmarks that look like: int average(a, b) { return (a + b) / 2; } main() { int sum; for (int i = 0; i < 100000; i++) { for (int j = 0; j < 100000; j++) { sum += average(i, j); } } if (sum != 123) printf("!"); } Instead of: int average(a, b) { return (a + b) / 2; } main() { for (int i = 0; i < 100000; i++) { for (int j = 0; j < 100000; j++) { average(i, j); } } }
- agnivade 9y agoAh I see ! Gotcha :) Yes, it seems Go is smart enough not to eliminate those values entirely. I think this might be a better way to be sure that the function will be computed entirely. `_ = myatan2(-479, 123)` The result is same though. I will update the post.
- aleksi 9y agoEven better is to make a global var sink interface{}, and assign to it. https://github.com/golang/go/issues/14813 https://github.com/golang/go/issues/14813