Re: Inserter facing up/north slower than other directions
Posted: Wed May 24, 2017 4:34 pm
Nice, took 2 years but great. My ocd can finally rest in pieces.
www.factorio.com
https://forums.factorio.com/
First, awesome to get it fixed now!Twinsen wrote:The problem was a bit deeper. The vector given to the atan2 was rotated imprecisely.
I don't understand the question.Zulan wrote:In any case, are you just trying to increase accuracy or are you also accepting and dealing with the eventual inaccuracies of floating point?
It is widely recognized that comparing two floating point numbers via == is bad. I don't think I could explain it better than this FAQ entry. I believe this applies here, despite any additional contributing factors to inaccuracy that may have been fixed now.Twinsen wrote:I'm not sure why the inserter moves so oddly. Most of it's behavior code is probably there since version 0.1 so probably not even the guy who wrote it(kovarex) would know why.
I don't understand the question.Zulan wrote:In any case, are you just trying to increase accuracy or are you also accepting and dealing with the eventual inaccuracies of floating point?
Most of the inaccuracies(and probably the silly inserter behavior) are from our custom trigonometrical functions which have to be both fast and deterministic. Floating point inaccuracies are not a problem.
Factorio requires determinism which means that if any of our compilers didn't produce the same results for floating point operations it would be an error so comparison via == is perfectly fine.Zulan wrote:It is widely recognized that comparing two floating point numbers via == is bad. I don't think I could explain it better than this FAQ entry. I believe this applies here, despite any additional contributing factors to inaccuracy.Twinsen wrote:I'm not sure why the inserter moves so oddly. Most of it's behavior code is probably there since version 0.1 so probably not even the guy who wrote it(kovarex) would know why.
I don't understand the question.Zulan wrote:In any case, are you just trying to increase accuracy or are you also accepting and dealing with the eventual inaccuracies of floating point?
Most of the inaccuracies(and probably the silly inserter behavior) are from our custom trigonometrical functions which have to be both fast and deterministic. Floating point inaccuracies are not a problem.
These are two different things. Floating point math (without aggressive optimization) is both deterministic and approximate at the same time.Rseding91 wrote:Factorio requires determinism which means that if any of our compilers didn't produce the same results for floating point operations it would be an error so comparison via == is perfectly fine.Zulan wrote: It is widely recognized that comparing two floating point numbers via == is bad. I don't think I could explain it better than this FAQ entry. I believe this applies here, despite any additional contributing factors to inaccuracy.
You're not wrong. However, with the level of optimization required for something as central as inserter mechanics, having to use rounding in every conditional check would have a significant impact on performance.Zulan wrote:These are two different things. Floating point math (without aggressive optimization) is both deterministic and approximate at the same time.
You can very well deterministically compute something that should mathematically be 0 is not == 0. That is not wrong with fp math. Just because it is deterministic, doesn't mean that some obscure change in the code / mod breaks it again in some other way that will make you scratch your head for years. I thought that very bug was a pretty good example of that.
This is a good and important point - however two things:IronCartographer wrote:You're not wrong. However, with the level of optimization required for something as central as inserter mechanics, having to use rounding in every conditional check would have a significant impact on performance.Zulan wrote:These are two different things. Floating point math (without aggressive optimization) is both deterministic and approximate at the same time.
You can very well deterministically compute something that should mathematically be 0 is not == 0. That is not wrong with fp math. Just because it is deterministic, doesn't mean that some obscure change in the code / mod breaks it again in some other way that will make you scratch your head for years. I thought that very bug was a pretty good example of that.
Even if your compilers all produce the same comparison operation, different FP hardware executing it may not return the same result, which could probably lead to desyncs in MP.Rseding91 wrote:Factorio requires determinism which means that if any of our compilers didn't produce the same results for floating point operations it would be an error so comparison via == is perfectly fine.Zulan wrote:It is widely recognized that comparing two floating point numbers via == is bad. I don't think I could explain it better than this FAQ entry. I believe this applies here, despite any additional contributing factors to inaccuracy.Twinsen wrote:I'm not sure why the inserter moves so oddly. Most of it's behavior code is probably there since version 0.1 so probably not even the guy who wrote it(kovarex) would know why.
I don't understand the question.Zulan wrote:In any case, are you just trying to increase accuracy or are you also accepting and dealing with the eventual inaccuracies of floating point?
Most of the inaccuracies(and probably the silly inserter behavior) are from our custom trigonometrical functions which have to be both fast and deterministic. Floating point inaccuracies are not a problem.
Could, but so far hasn't. And with the sample size we have I'm 99.99% confident in saying they all produce the same result.TwoD wrote:Even if your compilers all produce the same comparison operation, different FP hardware executing it may not return the same result, which could probably lead to desyncs in MP.
does anyone know an example of x86/x64 hardware (except with the Pentium bug) that would produce non IEEE floating point operation defined results? And I'm not talking about enhanced precision extensions etc, but hardware that simply does not allow for a correct IEEE mode.Rseding91 wrote:Could, but so far hasn't. And with the sample size we have I'm 99.99% confident in saying they all produce the same result.TwoD wrote:Even if your compilers all produce the same comparison operation, different FP hardware executing it may not return the same result, which could probably lead to desyncs in MP.
Yes, it's unlikely you'd find such cases, at least in machines produced around or after 2008 when the current version of the standard was made official. Factorio does seem to run well on quite dated hardware though.BenSeidel wrote:does anyone know an example of x86/x64 hardware (except with the Pentium bug) that would produce non IEEE floating point operation defined results? And I'm not talking about enhanced precision extensions etc, but hardware that simply does not allow for a correct IEEE mode.Rseding91 wrote:Could, but so far hasn't. And with the sample size we have I'm 99.99% confident in saying they all produce the same result.TwoD wrote:Even if your compilers all produce the same comparison operation, different FP hardware executing it may not return the same result, which could probably lead to desyncs in MP.
It's not even unlikely, it's impossible. We're talking about x86-64, so there simply are no differences in how the hardware executes FP instructions. If there were, it would be a huge hardware bug.TwoD wrote: Even if your compilers all produce the same comparison operation, different FP hardware executing it may not return the same result, which could probably lead to desyncs in MP.
Sometimes compilers behave in unexpected way. For example we had issue with MSVC 2015 not respecting type of primitive constexpr types: constexpr float noiseVariance = 0.28874039688617059; ...noiseValriance would be treated as double, so result of myFloat * noiseVariance would be double instead of expected float, and it this expression was used as function argument, overload for double would be called instead of one for float.Zulan wrote:It's not even unlikely, it's impossible. We're talking about x86-64, so there simply are no differences in how the hardware executes FP instructions. If there were, it would be a huge hardware bug.TwoD wrote: Even if your compilers all produce the same comparison operation, different FP hardware executing it may not return the same result, which could probably lead to desyncs in MP.
Yeah, we have to be carefull with using std math functions, we use implementations from various places (randomly found on internet).Of course, Factorio is not at liberty to freely use unsafe fast-math compiler-optimizations. Another challenge might be portable choice of math libraries. For instance I don't know if there is any guarantee that std::sin always returns the exact same result for different implementations of the standard library.
Rounding mode and other floating point control flags should be context-switched along with the rest of the floating point register state when switching threads. They're global from the *hardware's* point of view, but so are the actual floating point registers; it's up to the multitasking kernel to do the right thing here, and it'd be a kernel bug if this didn't happen.posila wrote:As for HW, we worry CPU flags which change how floating point operations are rounded. AFAIK the flags are global, so if any application changes them, it affects all applications on the system. Other than that results of instructions should be same on every x86-64 CPU.
Exactly. There's a lengthy article about the topic here: https://randomascii.wordpress.com/2013/ ... terminism/ - I think Factorio should be fine.torne wrote:Rounding mode and other floating point control flags should be context-switched along with the rest of the floating point register state when switching threads. They're global from the *hardware's* point of view, but so are the actual floating point registers; it's up to the multitasking kernel to do the right thing here, and it'd be a kernel bug if this didn't happen.posila wrote:As for HW, we worry CPU flags which change how floating point operations are rounded. AFAIK the flags are global, so if any application changes them, it affects all applications on the system. Other than that results of instructions should be same on every x86-64 CPU.
It isn't about determinism. Try this:Rseding91 wrote:Factorio requires determinism which means that if any of our compilers didn't produce the same results for floating point operations it would be an error so comparison via == is perfectly fine.Zulan wrote:It is widely recognized that comparing two floating point numbers via == is bad. I don't think I could explain it better than this FAQ entry. I believe this applies here, despite any additional contributing factors to inaccuracy.
Code: Select all
#include <stdio.h>
int main () {
double a = 0.1;
double b = 0.2;
double c = 0.3;
if (a + b == c) {
printf("%f == %f\n", a + b, c);
} else {
printf("%f != %f\n", a + b, c);
};
};