Hacker News new | ask | show | jobs
by adrian_b 21 days ago
If you compute a limit numerically, the decision that you have reached the limit must normally be taken long before there is any possibility of underflow, i.e. of generating denormals.

Typically you compute the difference between 2 adjacent terms of the convergent sequence and you decide that you have reached the limit when adding the difference to the current term to get the next does not change it (or when the relative error is smaller than some threshold). At this time the difference will still be many orders of magnitude greater than a denormal.

If the limit happens to be zero, then what you describe can happen. The programs where this can happen normally combine two different criteria to decide that the limit has been reached, i.e. that either the relative error is small enough, i.e. like I said that adding the difference to the previous term does not change it, or that the absolute error is small enough, i.e. that the difference is smaller than some threshold. The absolute error used as threshold is normally chosen based on what is physically meaningful in that problem, i.e. depending on what kind of physical quantity corresponds to the values of the terms of the convergent series.

An example of applications where the users must configure both relative errors and absolute errors, to be used as criteria of convergence, are the SPICE-like programs used to simulate electronic circuits, where the user must configure both a generally-applicable relative error, and absolute errors for different kinds of physical quantities, e.g. an absolute error for voltages and an absolute error for electric currents, which will be used, respectively, when a sequence of voltages converges towards zero or a sequence of currents converges towards zero, so that the absolute error criterion will be satisfied before the relative error criterion is satisfied.

In any case, in a correct program the attempt to find the limit should always stop before underflows become possible, so denormals should never be generated if the underflow exceptions are masked.

Denormals can appear in a lot of cases when almost equal values are subtracted, e.g. in the solution of many kinds of badly conditioned equations, but in most such cases there may exist alternative formulae that avoid underflows, i.e. the generation of denormals.

In general, when denormals appear, this signals bugs in the program, which must be investigated and fixed. The purpose of denormals is to allow the programmer to not fix the bugs, without causing catastrophic errors, like those that can happen when underflows generate null results, i.e. when "denormals are flushed to zero".

Careful programmers should nonetheless fix any bugs that generate denormals.

1 comments

Ah! So let me paraphrase to make sure I understand. In your experience, the real use case of denormals is not that you want to compute with them. It's that they are a useful error signal, because they typically indicate that the equations are badly conditioned, which means the results cannot be trusted. So in that scenario, silently flushing them to zero is bad, but so is silently computing with them. What you really want is for denormals to raise an exception?
They are indeed a useful error signal, like also infinities or NaNs.

Moreover, they are much more benign than infinities or NaNs, which signal bugs that you most likely have to fix.

Denormals cause only very small errors, which may be acceptable in most applications. Therefore you may choose to ignore such bugs and not fix them, because a modified algorithm that avoids underflows may be significantly more complex than the original algorithm.

Configuring the non-standard option to flush denormals to zero is bad for two reasons. Not only it removes evidence that something bad has happened, but unlike with denormals, this can cause huge errors, even infinite errors.

When the operations are done according to the IEEE standard, every operation has a limit for the relative error and it is possible to do a numeric analysis of some computational algorithm and estimate the maximum errors that can affect its results.

When underflows generate neither exceptions nor denormals, all guarantees are removed and you can no longer predict anything about the final errors of an algorithm.