bertiniteam / b2

Bertini 2.0: The redevelopment of Bertini in C++.
92 stars 34 forks source link

Check and ensure Num_Traits for MPFR_float #11

Open timothodge opened 9 years ago

timothodge commented 9 years ago

Must check the following parameters in Num_Traits for trustworthy results in MPFR_float:

ReadCost MulCost AddCost Dummy_Precision

What are these?

timothodge commented 7 years ago

Reading from the eigen documentation: https://eigen.tuxfamily.org/dox/structEigen_1_1NumTraits.html

They explain that ReadCost, MulCost, AddCost represent a rough estimate of the number of CPU cycles needed to use move / add / mul instructions respectively, They assume the data is already stored in CPU registers. As an additional note they do not do architecture specifics, and are purposely vague.

As for Dummy_Precision, it seems to be used to make a default tolerance for the "fuzzy operators".

Moving this issue forward, how best do we check the Num_Traits for MPFR_float?

ofloveandhate commented 7 years ago

I think that this kind of testing should be done perhaps via the bertini_timing suite. We need these kinds of numbers for not only eigen stuff, but also for some of the internals of adaptive precision. namely, in papers AMP1 and AMP2, there are some numbers computed that describe how expensive multiprecision is, as a function of the bitlength. we need to compute these numbers again

ofloveandhate commented 7 years ago

right now, here's what we have in include/bertini2/eigen_extensions.hpp:

using mpfr_float = bertini::mpfr_float;
    template<> struct NumTraits<mpfr_float> : GenericNumTraits<mpfr_float> // permits to get the epsilon, dummy_precision, lowest, highest functions
    {

        typedef mpfr_float Real;
        typedef mpfr_float NonInteger;
        typedef mpfr_float Nested;
        enum {
            IsComplex = 0,
            IsInteger = 0,
            IsSigned = 1,
            RequireInitialization = 1, // yes, require initialization, otherwise get crashes
            ReadCost = 20,
            AddCost = 30,
            MulCost = 40
        };

        inline static Real highest() {

            return (mpfr_float(1) - epsilon()) * pow(mpfr_float(2),mpfr_get_emax()-1);//);//DefaultPrecision());
        }

        inline static Real lowest() {
            return -highest();
        }

        inline static Real dummy_precision()
        {
            using bertini::DefaultPrecision;
            return pow( mpfr_float(10),-int(DefaultPrecision()-3));
        }

        inline static Real epsilon()
        {
            using bertini::DefaultPrecision;
            return pow(mpfr_float(10),-int(DefaultPrecision()));
        }
        //http://www.manpagez.com/info/mpfr/mpfr-2.3.2/mpfr_31.php
    };

are these 20/30/40 appropriate? should they be higher or lower? i think we need to test in order to answer this question.

ofloveandhate commented 7 years ago

and in amp_tracker.hpp:

inline
        mpfr_float ArithmeticCost(unsigned precision)
        {
            if (precision==DoublePrecision())
                return 1;
            else
                return mpfr_float("10.35") + mpfr_float("0.13") * precision;
        }

these values are directly from the AMP papers, not empirical measurement on the current implementations. i would love for these to be computed on a particular environment, and read in from something like config.h, etc. and i think the appropriate place might be in bertini_timing. thoughts?