discuss-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Discuss-gnuradio] volk float32->int8 kernel and thus float_to_char


From: CEL
Subject: Re: [Discuss-gnuradio] volk float32->int8 kernel and thus float_to_char block round or floor, depending on VOLK machine
Date: Sat, 9 Jun 2018 19:24:19 +0000

Hi Paul,

I agree with everything you say. Float to char should behave *exactly*
like float to int and short. Will fix it in that way. Will also have a
truncating version, maybe. I've just added 3 lines of code to the
current implementation to demonstrate it's trivial to change the
rounding mode. X87 FPUs are darn mighty things.

This brings me to another aspect: As far as I can tell from this height
is that VOLK code absolutely neglects to configure the FPU to a known
state. If the calling thread decides to do a   

_MM_SET_ROUNDING_MODE(_MM_ROUND_TOWARD_ZERO);

before calling volk_32f_s32f_convert_8i, all the kernels behave like
the truncate-to-0 generic kernel. That can't be what we want, nor is it
documented.

So, that's a bigger issue with VOLK: on one hand, we'd want to set that
SIMD FPU control register (MXCSR) on every entry into a volk kernel
that uses rounding, under- or overflowing SIMD intrinsics to have
defined behaviour. Since we are nice programmers, we don't want to have
surprising side effects, so we'd restore it to its original state on
exit... I see pipeline flush and performance bottleneck right there,
but it's IA64 calling convention to save and restore as callee. 

Best regards,
Marcus
On Sat, 2018-06-09 at 20:18 +0200, Paul Boven wrote:
> Hi Marcus,
> 
> I would prefer that when going from float to int, every 'bin' should 
> have equal size. So I can think of two ways to do that:
> 
> 1) zero corresponds to [-0.5 : 0.49999999]
> 
> or
> 
> 2) zero corresponds to [0.0 : 0.999999]
> 
> whereas the 'generic' optimization does
> 
> 3) zero corresponds to [-1 to 0.999999]
> 
> The second was actually the behaviour I was expecting, and I was 
> pleasantly surprised when GnuRadio seemed to do the first - but then 
> occasionally it doesn't.
> 
> I just did a quick test in python3, and there, the range of int(x)
> for 
> zero runs [-0.999999 : 0.999999], so I'm expecting most programming 
> languages to behave that way.
> 
> So, I guess a programmer would expect the behaviour as in the third 
> case. Someone who is converting radio signals might want either the 
> first or second case, as otherwise you end up with some interesting 
> non-linearities.
> 
> The gnuplot helpfile states: " The `int(x)` function returns the
> integer 
> part of its argument, truncated toward zero."
> 
> But gnuplot also provides functions like 'floor(x)' and ceil(x).
> 
> So the real question is still, do we want the behaviour of int(x),
> or 
> the behaviour that an analog to digital converter would have?
> 
> Finally, I'd say we want the behaviour to be the same for Int, Short
> and 
> Char. So I ran a few more tests.
> 
> With Volk enabled, Float to Int, Short and Char treat [-0.5 :
> 0.499999] 
> as zero, with the occasional glitch for Char.
> 
> volk_32f_s32f_convert_16i a_avx u_avx
> volk_32f_s32f_convert_32i a_avx u_sse2
> 
> With these conversions for Int and Short also switched to 'generic 
> generic', I get the same results:
> 
> Short zero: [-0.5 : 0.499999]
> Int zero:   [-0.5 : 0.499999]
> 
> So, assuming I carried out these tests correctly, the odd one out
> seems 
> to be the generic case for float to char conversion.
> 
> Note that Volk in the 16 bit and 32 bit case uses a function called 
> 'rintf' in the conversions. From its manpage:
> 
> "(...) round  their argument  to  an integer value in floating-point 
> format".
> 
> So I say this boils down to a bug in the 'generic' float to char
> case.
> 
> This is not a fix to make lightly, because somebody is going to have 
> their flowchart break because of this. Then again, in the current 
> situation the outcome depends on which optimizations your machine 
> happens to have available, so that's also quite bad.
> 
> Possibly there is also an optimization opportunity of never using 
> 'generic' even at the block edge when acceleration is available by 
> choosing the right size of blocks, but that's probably a small gain.
> 
> Regards, Paul Boven.
> 
> 
> 
> On 06/09/2018 07:18 PM, Müller, Marcus (CEL) wrote:
> > Hi Paul,
> > 
> > yes, this seems to be the case where the "naive" C implementation
> > behaves differently from all the SIMD ones:
> > 
> > As far as I know – but I'm desparately looking for any standards
> > document that specifies that – doing a
> > 
> > int8_t val = (int8_t) 8.8f;
> > 
> > will always lead to 8, whereas
> > 
> > int8_t val = (int8_t) -8.8f;
> > 
> > would always lead to -8.
> > 
> > Now, for the conversion operations used in the SIMD kernels, it
> > depends
> > on specific flags being set in FPU-control registers (MXCSR, it
> > seems).
> > Ummmm. Noone set these to give identical results as the native C
> > conversion above, so if I set the tolerance in the kernel unit test
> > to
> > 0 instead of 1 (which it always should have been), I get a whole
> > lot of
> > failures. Great.
> > 
> > Normally, we'd stick with the what the generic version of a kernel
> > gives us.
> > 
> > I'd do that here, too. But: that would lead to a non-rounding
> > behaviour... I'm breaking someone's porcelain here, no matter what
> > I
> > do.
> > 
> > Any ideas?
> > 
> > Best regards,
> > Marcus
> > 
> > On Sat, 2018-06-09 at 18:24 +0200, Paul Boven wrote:
> > > Hi Marcus,
> > > 
> > > Just reran the test after editing volk_config, and the result is
> > > somewhat surprising:
> > > 
> > > Every float in [-1:1] now converts to zero. Every float in [1:2]
> > > now
> > > converts to 1. Whereas it should be [-0.5:0.5] and [0.5:1.5].
> > > 
> > > It seems that most of the time, the u_sse2 converter is used, but
> > > at
> > > the
> > > end of each multiple of 8192 bytes, a few are done with the
> > > 'generic'
> > > converter - that would match perfectly with the observed
> > > behaviour.
> > > 
> > > It was also pointed out to me (on irc, unfortunately no longer in
> > > my
> > > history) that it is strange that for some acceleration types,
> > > there
> > > is a
> > > cast to int16_t instead of int8_t at the end of the routine,
> > > e.g.:
> > > 
> > > https://github.com/gnuradio/volk/blob/master/kernels/volk/volk_32
> > > f_s3
> > > 2f_convert_8i.h#L200
> > > 
> > > I had not really looked into that before because having run the
> > > volk_profile seemed to make no difference.
> > > 
> > > Regards, Paul Boven.
> > > 
> > > On 06/09/2018 06:08 PM, Müller, Marcus (CEL) wrote:
> > > > I can reproduce these, but do the errors disappear for you if
> > > > you
> > > > replace "u_sse2 u_sse2" with "generic generic" on that line?
> > > > 
> > > > 
> > > > Best regards,
> > > > Marcus
> > > > On Sat, 2018-06-09 at 18:04 +0200, Paul Boven wrote:
> > > > > Hi Marcus,
> > > > > 
> > > > > This machine did not yet have a volk_config when I ran these
> > > > > tests.
> > > > > 
> > > > > I have since run volk_profile and rebooted, and the Float-
> > > > > >Char
> > > > > quantization bug still occurs.
> > > > > 
> > > > > $ volk-config-info --machine
> > > > > avx2_64_mmx_orc
> > > > > 
> > > > > $ grep volk_32f_s32f_convert_8i .volk/volk_config
> > > > > volk_32f_s32f_convert_8i u_sse2 u_sse2
> > > > > 
> > > > > Regards, Paul Boven.
> > > > > 
> > > > > On 06/09/2018 05:30 PM, Müller, Marcus (CEL) wrote:
> > > > > > Hi Paul,
> > > > > > 
> > > > > > hm, OK, considering the actual conversion is done in VOLK,
> > > > > > can
> > > > > > you
> > > > > > tell
> > > > > > us
> > > > > > 
> > > > > > * whether ~/.volk/volk_config exists (and if so, its
> > > > > > contents
> > > > > > regarding
> > > > > > volk_32f_s32f_convert_8i )
> > > > > > * what the output of `volk-config-info --machine` is?
> > > > > > 
> > > > > > Thanks,
> > > > > > Marcus
> > > > > > 
> > > > > > On Sat, 2018-06-09 at 17:13 +0200, Paul Boven wrote:
> > > > > > > Hi everyone,
> > > > > > > 
> > > > > > > I'm trying to perform 2 bit sampling of an RF signal. In
> > > > > > > one
> > > > > > > approach,
> > > > > > > I'm using a float->char block, and noticed that around
> > > > > > > zero,
> > > > > > > a
> > > > > > > number
> > > > > > > of
> > > > > > > float inputs become quantized in a bin that's one off
> > > > > > > from
> > > > > > > the
> > > > > > > correct
> > > > > > > value. The ones that are wrong are always off by one,
> > > > > > > with
> > > > > > > their
> > > > > > > quantization error always in the direction of zero.
> > > > > > > 
> > > > > > > The problem can be demonstrated with a really simple
> > > > > > > flowchart,
> > > > > > > using
> > > > > > > the following blocks:
> > > > > > > 
> > > > > > > * Noise Source (Noise Type: Gaussian, Amplitude: 1, Seed:
> > > > > > > 0,
> > > > > > > Output
> > > > > > > type: Float)
> > > > > > > * Throttle
> > > > > > > The throttle is then connected to two blocks:
> > > > > > > * A file-sink (Type Float) and a
> > > > > > > * 'Float to Char' block.
> > > > > > > * The float to char block is again connected to a File
> > > > > > > Sink,
> > > > > > > now
> > > > > > > of
> > > > > > > type
> > > > > > > Char.
> > > > > > > 
> > > > > > > As an example, I've plotted all the samples that
> > > > > > > quantized as
> > > > > > > zero.
> > > > > > > These should fall in the range [-0.5:0.5], but
> > > > > > > occasionally
> > > > > > > we
> > > > > > > also
> > > > > > > get
> > > > > > > hits that lie within [-1:1]. These mishaps are rare
> > > > > > > (about
> > > > > > > one in
> > > > > > > 2000).
> > > > > > > It also shows that they only occur at multiples of 8192
> > > > > > > samples,
> > > > > > > and
> > > > > > > zooming in reveals that they always happen shortly before
> > > > > > > the
> > > > > > > next
> > > > > > > multiple of 8192, not after.
> > > > > > > 
> > > > > > > For other values than 0, the same applies, but the
> > > > > > > misquantizations
> > > > > > > are
> > > > > > > only in one direction, ending up in a lower bin if the
> > > > > > > input
> > > > > > > is
> > > > > > > positive, or in a higher bin if the input is negative.
> > > > > > > Again,
> > > > > > > the
> > > > > > > misquantizations only occur in half the bin: For a value
> > > > > > > of
> > > > > > > 1,
> > > > > > > the
> > > > > > > float
> > > > > > > value should be in [0.5:1.5], but occasionally a value in
> > > > > > > [1.5:2]
> > > > > > > also
> > > > > > > ends up being quantized as 1.
> > > > > > > 
> > > > > > > This seems to me a bug that is somehow related to
> > > > > > > internal
> > > > > > > block
> > > > > > > boundaries, but I'm not familiar enough with the
> > > > > > > internals of
> > > > > > > GnuRadio
> > > > > > > to figure out just what's going wrong.
> > > > > > > 
> > > > > > > The problem does NOT occur when converting to Short or
> > > > > > > Int.
> > > > > > > 
> > > > > > > This is using GnuRadio 3.7.11 (as packaged with Ubuntu
> > > > > > > 18.04).
> > > > > > > 
> > > > > > > Regards, Paul Boven.
> > > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > _______________________________________________
> > > > > > > Discuss-gnuradio mailing list
> > > > > > > address@hidden
> > > > > > > https://lists.gnu.org/mailman/listinfo/discuss-gnuradio
> 
> 

Attachment: smime.p7s
Description: S/MIME cryptographic signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]