masking and unmasking arithmetic exceptions - could it be usefull?

Started by
6 comments, last by Vortez 10 years, 3 months ago

When doing fpu or sse arithmetic there are options for mask or unmask

some arithmetic exceptions (about 5 of them), could it be usefull to work

with them (change them for some purposes) or in gamedev they are not

usefull?

Advertisement

In my indie game, I leave _EM_INVALID, _EM_ZERODIVIDE and _EM_OVERFLOW on pretty much all the time in debug mode. I only disable them when I'm calling out to some 3rd party library that misbehaves* and I can't fix. I find it very helpful to catch floating point exceptions as early as possible before they start producing undefined behaviour.

_EM_UNDERFLOW, _EM_INEXACT and _EM_DENORMAL are less useful because they fire all the time, and are almost never an error condition. However, I still make use of them. I plan to support lock-step multiplayer in the future, so there's a simulation part of my game which isn't allowed to use floating point numbers in case they behave differently on different machines, builds, optimisation settings, etc. To 'enforce' the no-float rule, I enable all the spurious exceptions in the knowledge they will almost certainly fire if I accidentally do any floating point math within the simulation.

*I say misbehave, but sometimes optimised code is written that is deliberately allowed to create infinities and then handles them correctly.

In my indie game, I leave _EM_INVALID, _EM_ZERODIVIDE and _EM_OVERFLOW on pretty much all the time in debug mode. I only disable them when I'm calling out to some 3rd party library that misbehaves* and I can't fix. I find it very helpful to catch floating point exceptions as early as possible before they start producing undefined behaviour.

_EM_UNDERFLOW, _EM_INEXACT and _EM_DENORMAL are less useful because they fire all the time, and are almost never an error condition. However, I still make use of them. I plan to support lock-step multiplayer in the future, so there's a simulation part of my game which isn't allowed to use floating point numbers in case they behave differently on different machines, builds, optimisation settings, etc. To 'enforce' the no-float rule, I enable all the spurious exceptions in the knowledge they will almost certainly fire if I accidentally do any floating point math within the simulation.

*I say misbehave, but sometimes optimised code is written that is deliberately allowed to create infinities and then handles them correctly.

well interesting, could you say yet maybe how do you handle this exceptions?

This optymistion code remerk is also interesting (how much % speedup gain can be obrtained this way and how?)

Are the INVALID and DIVIDE set on by default in windows? Does the

api called by program not change the fpu/sse state ?

On some systems *cough* PPC *cough* denormal values are not supported by hardware -- if they're used, then the hardware has to jump to a software routine that can emulate support for them. On these systems, if you accidentally start using a denormal value, it will absolutely ruin the performance of your game, and it can be hard to determine why it's happening, so it's common on these systems to enable the FPU exception for use of denormals (and not handle the exception, basically to make the game crash on that line of code so you can fix the data).

The only time I've seen these FPU exceptions enabled in games, was during debugging. If you're getting NaN results and you don't know why, it's handy to be able to set a breakpoint that will fire at the moment that you divide by zero, so that you can fix your code wink.png

I've never seen software that's built around catching/handling these exceptions.

On some systems *cough* PPC *cough* denormal values are not supported by hardware -- if they're used, then the hardware has to jump to a software routine that can emulate support for them. On these systems, if you accidentally start using a denormal value, it will absolutely ruin the performance of your game, and it can be hard to determine why it's happening, so it's common on these systems to enable the FPU exception for use of denormals (and not handle the exception, basically to make the game crash on that line of code so you can fix the data).

The only time I've seen these FPU exceptions enabled in games, was during debugging. If you're getting NaN results and you don't know why, it's handy to be able to set a breakpoint that will fire at the moment that you divide by zero, so that you can fix your code wink.png

I've never seen software that's built around catching/handling these exceptions.

can disabling them speed up the program flow?

if they are not slowing leaving them on in release probably would be

also the better option then masking them (or not?)

In my indie game, I leave _EM_INVALID, _EM_ZERODIVIDE and _EM_OVERFLOW on pretty much all the time in debug mode. I only disable them when I'm calling out to some 3rd party library that misbehaves* and I can't fix. I find it very helpful to catch floating point exceptions as early as possible before they start producing undefined behaviour.

_EM_UNDERFLOW, _EM_INEXACT and _EM_DENORMAL are less useful because they fire all the time, and are almost never an error condition. However, I still make use of them. I plan to support lock-step multiplayer in the future, so there's a simulation part of my game which isn't allowed to use floating point numbers in case they behave differently on different machines, builds, optimisation settings, etc. To 'enforce' the no-float rule, I enable all the spurious exceptions in the knowledge they will almost certainly fire if I accidentally do any floating point math within the simulation.

*I say misbehave, but sometimes optimised code is written that is deliberately allowed to create infinities and then handles them correctly.

well interesting, could you say yet maybe how do you handle this exceptions?

This optymistion code remerk is also interesting (how much % speedup gain can be obrtained this way and how?)

Are the INVALID and DIVIDE set on by default in windows? Does the

api called by program not change the fpu/sse state ?

I don't handle the exceptions, I have them enabled only in debug and consider them as errors. If they occur while I'm debugging, program execution stops and I can debug and fix the problem.

The optimisation remark was perhaps misleading. What I meant, is that I've sometimes seen code in collision intersection testing (or maybe it was frustum culling) where it was doing a floating point divide, without bothering to check if the denominator was zero. The code was correct as it only cared about the sign of the result, so whereas usually a divide by zero is a sign of a bug that needs fixing, it's not necessarily the case. All I was saying is that a divide by zero is not necessarily a bug.

AFAIK, floating point exceptions are off by default (at least in the environments I've worked in).

I recommend Bruce Dawson's series of articles on floating point numbers. This is the one where he talks about exceptions: http://www.altdevblogaday.com/2012/04/20/exceptional-floating-point/ (read the rest too though, they're great). The code I use to switch exceptions on/off is roughly based on the classes in that blog.

edit: Well behaved APIs shouldn't change the fpu/sse state (or if they do, they should put it back again). A long time ago, DirectX used to mess with the rounding mode, I believe, but I'm pretty sure it doesn't anymore.

AFAIK, floating point exceptions are off by default (at least in the environments I've worked in).

For sure at least division by zero is on - it causes the "send error raport/dont' send" dialogo in windows when unhandled..

I recently get to know that probably cast float to int cant raise an

exception when float>int but this is probably masked one.


can disabling them speed up the program flow?

Instead of guessing, profile, it's the only way to know for sure.

This topic is closed to new replies.

Advertisement