POV-Ray 3.7 is part of the SPEC 2017 suite of benchmarks. While running POVRAY
from SPEC, I see some very significant performance differences that are
triggered by some very slight numerical differences. Apparently, the very slight
numerical differences cause different code paths to be taken resulting in the
very significant performance differences in subsequently executed routines.
The 3.7 version file involved is quadrics.cpp, and the routine involved is
In Compute_Quadric_BBox(), some values are setup that control how much work is
ultimately done elsewhere in the program. In this routine, some setup work is
performed based on all sort of floating point compares to 0.0: > 0.0, < 0.0, ==
0.0, and != 0.0. With these critical comparisons to 0.0, slight numerical
differences can result in a different setup, so it is very important that if a
value is intended to be 0.0, that it is actually 0.0.
And obtaining actual 0.0 values is partially obtained by setting values that are
close to zero to actually be 0.0, such as, the below POVRAY code.
/* Set small values to 0. */
if (fabs(A) < EPSILON) A = 0.0;
if (fabs(B) < EPSILON) B = 0.0;
if (fabs(C) < EPSILON) C = 0.0;
if (fabs(D) < EPSILON) D = 0.0;
if (fabs(E) < EPSILON) E = 0.0;
if (fabs(F) < EPSILON) F = 0.0;
if (fabs(G) < EPSILON) G = 0.0;
if (fabs(H) < EPSILON) H = 0.0;
if (fabs(I) < EPSILON) I = 0.0;
if (fabs(J) < EPSILON) J = 0.0;
However, after the above adjustments of some small values to 0.0 are completed,
a few of the values are recalculated, which once again results in some small
values that are not equal to zeo, such as J for the SPEC test case. Certain
compilers versions or compiler options may result in an exact value of
0.000000e+00, but with most compiler versions and options, due to the limited
precision of floating point operations, the J values end up being something
close to zero, like 8.881784e-16, but not actually zero, resulting in the
different setup to be performance and much poorer performance.
/* Recalculate coefficients. */
D += A * T1[X];
G += E * T1[Y];
I += H * T1[Z];
J -= T1[X]*(A*T1[X] + 2.0*D) + T1[Y]*(E*T1[Y] + 2.0*G) + T1[Z]*(H*T1[Z] +
If the J value is simply re-adjusted back to 0., as was done earlier, then much
better performance is obtained without changing the correctness of the generated
As mentioned above, SPEC is based off of POV-Ray 3.7 and although file names
have changed and updates have occurred in 3.8, the same basic issue is still
appears to be present in 3.8.
So my question is:
Should the "set small values to 0." adjustments be re-made, primarily for "J",
so that consistent comparisons can be make to 0.0, or was it intentional
not to make any readjustments to "set small values to 0." after the "recalculate
coefficients" was performed?
Post a reply to this message