Skip to content

Performance cost of ::fpe_check() #32

Description

@risc26z

I've found that a large amount of CPU time is spent in the fpe_check() function (wrspice/include/fpe_check.h). In some tests I've made, this function uses more than a third of the total CPU time. Most of the time is spent in feclearexcept().

There's little point in clearing an exception that hasn't happened, so I rewrote the code so that feclearexcept() is called only if an exception is discovered. I also modified the code so that fetestexcept() is only called once.

This is essentially what I ended up with:

        if (!noerrret && Sp.GetFPEmode() == FPEcheck) {
            const int exflags_tested = FE_DIVBYZERO | FE_OVERFLOW | FE_INVALID;
            // read FP exception status into a temporary, which
            // can then be tested with minimal overhead
            int exflags = fetestexcept(exflags_tested);
            if (exflags != 0) {
                if (exflags & FE_DIVBYZERO)
                    err = E_MATHDBZ;
                else if (exflags & FE_OVERFLOW)
                    err = E_MATHOVF;
                // Ignore underflow, these really shouldn't be a problem.
                // else if (fetestexcept(FE_UNDERFLOW))
                //     err = E_MATHUNF;
                else if (exflags & FE_INVALID)
                    err = E_MATHINV;

                // feclearexcept() is slow (at least on x86-64), so try to
                // make sure we call it only when necessary.
                feclearexcept(FE_ALL_EXCEPT);
            }
        }

I haven't tested it thoroughly, but it seems to be considerably quicker. Any thoughts?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions