* [PATCH] utils: Use fma in qemu_strtosz @ 2021-03-14 23:48 Richard Henderson 2021-03-15 5:32 ` Thomas Huth ` (2 more replies) 0 siblings, 3 replies; 8+ messages in thread From: Richard Henderson @ 2021-03-14 23:48 UTC (permalink / raw) To: qemu-devel; +Cc: peter.maydell, berrange Use fma to simulatneously scale and round up fraction. The libm function will always return a properly rounded double precision value, which will eliminate any extra precision the x87 co-processor may give us, which will keep the output predictable vs other hosts. Adding DBL_EPSILON while scaling should help with fractions like 12.345, where the closest representable number is actually 12.3449*. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- util/cutils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/cutils.c b/util/cutils.c index d89a40a8c3..f7f8e48a68 100644 --- a/util/cutils.c +++ b/util/cutils.c @@ -342,7 +342,7 @@ static int do_strtosz(const char *nptr, const char **end, retval = -ERANGE; goto out; } - *result = val * mul + (uint64_t) (fraction * mul); + *result = val * mul + (uint64_t)fma(fraction, mul, DBL_EPSILON); retval = 0; out: -- 2.25.1 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH] utils: Use fma in qemu_strtosz 2021-03-14 23:48 [PATCH] utils: Use fma in qemu_strtosz Richard Henderson @ 2021-03-15 5:32 ` Thomas Huth 2021-03-15 13:20 ` Richard Henderson 2021-03-15 9:10 ` Philippe Mathieu-Daudé 2021-03-15 11:38 ` Eric Blake 2 siblings, 1 reply; 8+ messages in thread From: Thomas Huth @ 2021-03-15 5:32 UTC (permalink / raw) To: Richard Henderson, qemu-devel; +Cc: peter.maydell, berrange On 15/03/2021 00.48, Richard Henderson wrote: > Use fma to simulatneously scale and round up fraction. > > The libm function will always return a properly rounded double precision > value, which will eliminate any extra precision the x87 co-processor may > give us, which will keep the output predictable vs other hosts. > > Adding DBL_EPSILON while scaling should help with fractions like > 12.345, where the closest representable number is actually 12.3449*. > > Signed-off-by: Richard Henderson <richard.henderson@linaro.org> > --- > util/cutils.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/util/cutils.c b/util/cutils.c > index d89a40a8c3..f7f8e48a68 100644 > --- a/util/cutils.c > +++ b/util/cutils.c > @@ -342,7 +342,7 @@ static int do_strtosz(const char *nptr, const char **end, > retval = -ERANGE; > goto out; > } > - *result = val * mul + (uint64_t) (fraction * mul); > + *result = val * mul + (uint64_t)fma(fraction, mul, DBL_EPSILON); > retval = 0; > > out: Will this fix the failure that we're currently seeing with 32-bit builds? ( https://gitlab.com/qemu-project/qemu/-/jobs/1096980112#L3258 for example ) Reviewed-by: Thomas Huth <thuth@redhat.com> ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] utils: Use fma in qemu_strtosz 2021-03-15 5:32 ` Thomas Huth @ 2021-03-15 13:20 ` Richard Henderson 0 siblings, 0 replies; 8+ messages in thread From: Richard Henderson @ 2021-03-15 13:20 UTC (permalink / raw) To: Thomas Huth, qemu-devel; +Cc: peter.maydell, berrange On 3/14/21 11:32 PM, Thomas Huth wrote: > On 15/03/2021 00.48, Richard Henderson wrote: >> Use fma to simulatneously scale and round up fraction. >> >> The libm function will always return a properly rounded double precision >> value, which will eliminate any extra precision the x87 co-processor may >> give us, which will keep the output predictable vs other hosts. >> >> Adding DBL_EPSILON while scaling should help with fractions like >> 12.345, where the closest representable number is actually 12.3449*. >> >> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> >> --- >> util/cutils.c | 2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >> diff --git a/util/cutils.c b/util/cutils.c >> index d89a40a8c3..f7f8e48a68 100644 >> --- a/util/cutils.c >> +++ b/util/cutils.c >> @@ -342,7 +342,7 @@ static int do_strtosz(const char *nptr, const char **end, >> retval = -ERANGE; >> goto out; >> } >> - *result = val * mul + (uint64_t) (fraction * mul); >> + *result = val * mul + (uint64_t)fma(fraction, mul, DBL_EPSILON); >> retval = 0; >> out: > > Will this fix the failure that we're currently seeing with 32-bit builds? Yes. https://gitlab.com/rth7680/qemu/-/pipelines/270311986 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] utils: Use fma in qemu_strtosz 2021-03-14 23:48 [PATCH] utils: Use fma in qemu_strtosz Richard Henderson 2021-03-15 5:32 ` Thomas Huth @ 2021-03-15 9:10 ` Philippe Mathieu-Daudé 2021-03-15 11:40 ` Eric Blake 2021-03-15 13:19 ` Richard Henderson 2021-03-15 11:38 ` Eric Blake 2 siblings, 2 replies; 8+ messages in thread From: Philippe Mathieu-Daudé @ 2021-03-15 9:10 UTC (permalink / raw) To: Richard Henderson, qemu-devel; +Cc: peter.maydell, berrange On 3/15/21 12:48 AM, Richard Henderson wrote: > Use fma to simulatneously scale and round up fraction. "simultaneously" > The libm function will always return a properly rounded double precision > value, which will eliminate any extra precision the x87 co-processor may > give us, which will keep the output predictable vs other hosts. > > Adding DBL_EPSILON while scaling should help with fractions like > 12.345, where the closest representable number is actually 12.3449*. > > Signed-off-by: Richard Henderson <richard.henderson@linaro.org> > --- > util/cutils.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/util/cutils.c b/util/cutils.c > index d89a40a8c3..f7f8e48a68 100644 > --- a/util/cutils.c > +++ b/util/cutils.c > @@ -342,7 +342,7 @@ static int do_strtosz(const char *nptr, const char **end, > if (val > (UINT64_MAX - ((uint64_t) (fraction * mul))) / mul) { Shouldn't we use fma() here too? ^^^^^^^^^^^^^^^^^^^^^^^^^^ > retval = -ERANGE; > goto out; > } > - *result = val * mul + (uint64_t) (fraction * mul); > + *result = val * mul + (uint64_t)fma(fraction, mul, DBL_EPSILON); > retval = 0; > > out: > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] utils: Use fma in qemu_strtosz 2021-03-15 9:10 ` Philippe Mathieu-Daudé @ 2021-03-15 11:40 ` Eric Blake 2021-03-15 13:19 ` Richard Henderson 1 sibling, 0 replies; 8+ messages in thread From: Eric Blake @ 2021-03-15 11:40 UTC (permalink / raw) To: Philippe Mathieu-Daudé, Richard Henderson, qemu-devel Cc: peter.maydell, berrange On 3/15/21 4:10 AM, Philippe Mathieu-Daudé wrote: > On 3/15/21 12:48 AM, Richard Henderson wrote: >> Use fma to simulatneously scale and round up fraction. > > "simultaneously" > >> The libm function will always return a properly rounded double precision >> value, which will eliminate any extra precision the x87 co-processor may >> give us, which will keep the output predictable vs other hosts. >> >> Adding DBL_EPSILON while scaling should help with fractions like >> 12.345, where the closest representable number is actually 12.3449*. >> >> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> >> --- >> util/cutils.c | 2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >> diff --git a/util/cutils.c b/util/cutils.c >> index d89a40a8c3..f7f8e48a68 100644 >> --- a/util/cutils.c >> +++ b/util/cutils.c >> @@ -342,7 +342,7 @@ static int do_strtosz(const char *nptr, const char **end, >> if (val > (UINT64_MAX - ((uint64_t) (fraction * mul))) / mul) { > > Shouldn't we use fma() here too? ^^^^^^^^^^^^^^^^^^^^^^^^^^ Unlikely to make a difference in practice, but yes, consistency argues that we should perform the same computations. In fact, it may be worth factoring out the computation to be done once, instead of relying on the compiler to determine if fma() can undergo common subexpression elimination. > >> retval = -ERANGE; >> goto out; >> } >> - *result = val * mul + (uint64_t) (fraction * mul); >> + *result = val * mul + (uint64_t)fma(fraction, mul, DBL_EPSILON); >> retval = 0; >> >> out: >> > > -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3226 Virtualization: qemu.org | libvirt.org ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] utils: Use fma in qemu_strtosz 2021-03-15 9:10 ` Philippe Mathieu-Daudé 2021-03-15 11:40 ` Eric Blake @ 2021-03-15 13:19 ` Richard Henderson 1 sibling, 0 replies; 8+ messages in thread From: Richard Henderson @ 2021-03-15 13:19 UTC (permalink / raw) To: Philippe Mathieu-Daudé, qemu-devel; +Cc: peter.maydell, berrange On 3/15/21 3:10 AM, Philippe Mathieu-Daudé wrote: > On 3/15/21 12:48 AM, Richard Henderson wrote: >> Use fma to simulatneously scale and round up fraction. > > "simultaneously" > >> The libm function will always return a properly rounded double precision >> value, which will eliminate any extra precision the x87 co-processor may >> give us, which will keep the output predictable vs other hosts. >> >> Adding DBL_EPSILON while scaling should help with fractions like >> 12.345, where the closest representable number is actually 12.3449*. >> >> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> >> --- >> util/cutils.c | 2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >> diff --git a/util/cutils.c b/util/cutils.c >> index d89a40a8c3..f7f8e48a68 100644 >> --- a/util/cutils.c >> +++ b/util/cutils.c >> @@ -342,7 +342,7 @@ static int do_strtosz(const char *nptr, const char **end, >> if (val > (UINT64_MAX - ((uint64_t) (fraction * mul))) / mul) { > > Shouldn't we use fma() here too? ^^^^^^^^^^^^^^^^^^^^^^^^^^ Yep, I should have looked at the larger context. r~ > >> retval = -ERANGE; >> goto out; >> } >> - *result = val * mul + (uint64_t) (fraction * mul); >> + *result = val * mul + (uint64_t)fma(fraction, mul, DBL_EPSILON); >> retval = 0; >> >> out: >> > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] utils: Use fma in qemu_strtosz 2021-03-14 23:48 [PATCH] utils: Use fma in qemu_strtosz Richard Henderson 2021-03-15 5:32 ` Thomas Huth 2021-03-15 9:10 ` Philippe Mathieu-Daudé @ 2021-03-15 11:38 ` Eric Blake 2021-03-15 13:27 ` Richard Henderson 2 siblings, 1 reply; 8+ messages in thread From: Eric Blake @ 2021-03-15 11:38 UTC (permalink / raw) To: Richard Henderson, qemu-devel; +Cc: peter.maydell, berrange On 3/14/21 6:48 PM, Richard Henderson wrote: > Use fma to simulatneously scale and round up fraction. > > The libm function will always return a properly rounded double precision > value, which will eliminate any extra precision the x87 co-processor may > give us, which will keep the output predictable vs other hosts. > > Adding DBL_EPSILON while scaling should help with fractions like > 12.345, where the closest representable number is actually 12.3449*. > > Signed-off-by: Richard Henderson <richard.henderson@linaro.org> > --- > util/cutils.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/util/cutils.c b/util/cutils.c > index d89a40a8c3..f7f8e48a68 100644 > --- a/util/cutils.c > +++ b/util/cutils.c > @@ -342,7 +342,7 @@ static int do_strtosz(const char *nptr, const char **end, > retval = -ERANGE; > goto out; > } > - *result = val * mul + (uint64_t) (fraction * mul); > + *result = val * mul + (uint64_t)fma(fraction, mul, DBL_EPSILON); Don't you need to include <float.h> to get DBL_EPSILON? More importantly, this patch seems wrong. fma(a, b, c) performs (a * b) + c without intermediate rounding errors, but given our values for a and b, where mul > 1 in any situation we care about, adding 2^-53 is so much smaller than a*b that it not going to round the result up to the next integer. Don't you want to do fma(fraction, mul, 0.5) instead? -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3226 Virtualization: qemu.org | libvirt.org ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] utils: Use fma in qemu_strtosz 2021-03-15 11:38 ` Eric Blake @ 2021-03-15 13:27 ` Richard Henderson 0 siblings, 0 replies; 8+ messages in thread From: Richard Henderson @ 2021-03-15 13:27 UTC (permalink / raw) To: Eric Blake, qemu-devel; +Cc: peter.maydell, berrange On 3/15/21 5:38 AM, Eric Blake wrote: > On 3/14/21 6:48 PM, Richard Henderson wrote: >> Use fma to simulatneously scale and round up fraction. >> >> The libm function will always return a properly rounded double precision >> value, which will eliminate any extra precision the x87 co-processor may >> give us, which will keep the output predictable vs other hosts. >> >> Adding DBL_EPSILON while scaling should help with fractions like >> 12.345, where the closest representable number is actually 12.3449*. >> >> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> >> --- >> util/cutils.c | 2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >> diff --git a/util/cutils.c b/util/cutils.c >> index d89a40a8c3..f7f8e48a68 100644 >> --- a/util/cutils.c >> +++ b/util/cutils.c >> @@ -342,7 +342,7 @@ static int do_strtosz(const char *nptr, const char **end, >> retval = -ERANGE; >> goto out; >> } >> - *result = val * mul + (uint64_t) (fraction * mul); >> + *result = val * mul + (uint64_t)fma(fraction, mul, DBL_EPSILON); > > Don't you need to include <float.h> to get DBL_EPSILON? Apparently we get it via some other route. > More importantly, this patch seems wrong. fma(a, b, c) performs (a * b) > + c without intermediate rounding errors, but given our values for a and > b, where mul > 1 in any situation we care about, adding 2^-53 is so much > smaller than a*b that it not going to round the result up to the next > integer. Don't you want to do fma(fraction, mul, 0.5) instead? I tried that first, but that requires changes to the testsuite, where we have a *.7 result, and expect it to be truncated. I assumed adding 0.00*1 to 0.99*9 would still have an effect. I think I should have tried fma(fraction, mul, 0) as well, just to see if it's the elimination of extended-precision results that were the real problem. r~ ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2021-03-15 13:28 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2021-03-14 23:48 [PATCH] utils: Use fma in qemu_strtosz Richard Henderson 2021-03-15 5:32 ` Thomas Huth 2021-03-15 13:20 ` Richard Henderson 2021-03-15 9:10 ` Philippe Mathieu-Daudé 2021-03-15 11:40 ` Eric Blake 2021-03-15 13:19 ` Richard Henderson 2021-03-15 11:38 ` Eric Blake 2021-03-15 13:27 ` Richard Henderson
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).