discuss-gnuradio
[Top][All Lists]
Advanced

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

Re: [Discuss-gnuradio] Two more potential tag propagation improvements


From: Andy Walls
Subject: Re: [Discuss-gnuradio] Two more potential tag propagation improvements
Date: Sat, 06 Jan 2018 17:28:29 -0500

On Sat, 2018-01-06 at 12:13 -0500, Jeff Long wrote:
> How much error would be produced by having the executor determine 
> rr_in_offset and rr_out_offset by assuming the current rate holds
> over 
> the current window of data?
> 
> offset = (new_tag.offset - rr_in_offset) * mp_rrate + rr_out_offset
> + 
> one_half;

Because the runtime is making _assumptions_, ultimately the error is
unbounded as time progresses.  The growth of the error depends on the
particular situation.

So think of a graph with input offset as the x-axis, output offset on
the y-axis, and a piecewise linear curve with line segments joining
tuples (0, 0), (in1, out1), (in2, out2), (in3, out3), ...
with the slope of the the line segment joining any two points being the
current relative rate.

My suggestion has the runtime being told the (inN, outN) coordinates
and the slopes (aka relative rates), directly by the block's
general_work() function.  So the runtime's graph of input tag offset vs
output tag offset will be correct.


Your suggestion has the runtime making a guess at what the (inN, outN)
coordinates should be based on assumptions made by the runtime, and (I
think) the block informing the runtime of the slopes (aka relative
rates).  So in this case the runtime's graph will only be correct, if
the assumptions aren't violated.  If the assumptions are violated, the
graph in use can ever increasingly diverge from the correct grpah as
time goes on.

On a relative rate change, the runtime could guess at what the (inN,
outN) coordinate should be, using the resonable assumption that they
are the input and output tag offsets at the beginning (or end) of the
current call to general_work().  This could be error free as long as
block behaved as follows:

1. only one relative rate change is allowed in any one call to
general_work()

2. the relative rate change only happens at samples at the beginning
(or end) of work.

> This would not require an API change.
> 
> You could add a field rr_offset_mode to Block, give it default 
> RR_OFFSET_MODE_GLOBAL for the usual case, and RR_OFFSET_MODE_WINDOW
> for 
> those blocks that want to use the current rate for the current
> window.

I don't an explicit mode needs to be set by the block.  This can be
selected implicitly by the block with default arguments to the
set_relative_rate() calls, I think.

> RR_OFFSET_MODE_GLOBAL:
> offset = tag.offset * mp_rrate + one_half;
> 
> RR_OFFSET_MODE_WINDOW
> offset = (tag.offset - window_start_in) * mp_rrate + window_start_out
> + 
> one_half;
> 
> If there are blocks where this local linear assumption causes too
> much 
> error, those blocks can do their own tag propagation.

Yeah, that's always the fallback. :)


I'm a little leary of building in a mode where the runtime is making
assumptions, and needs those assumption not to be violated to get
things right.  I think it's asking for disappointing end user
experience in the long run.

But hey, I'll write up a changeset with both modes of operation in
place and see what it looks like. 

-Andy

> On 01/06/2018 10:01 AM, Andy Walls wrote:
> > Hi Marcus and Jeff:
> > 
> > So now that I've got something working for correct tag propagation
> > with
> > a static relative rate through one block, I'm ready to tackle some
> > other problems.
> > 
> > 1. The runtime performing (or at least assisting) correct tag
> > propagation for blocks with a changing relative rate.
> > 
> > 2. Precision tag propagation through multiple rate changing blocks
> > using fractional tag offsets.  See the discussion at
> > https://lists.gnu.org/archive/html/discuss-gnuradio/2017-11/msg0008
> > 9.html
> > for the gist of this one.
> > 
> > (If some thinks either of the above shouldn't be implemented, let
> > me know.
> > I don't want to waste time on dead-ends.)
> > 
> > The conceptual solutions for these require API changes that are not
> > backward compatable.  They can't be fixed on the master branch, and
> > they have to be fixed on the next branch.
> > 
> > #2 above is a big, wide ranging change, and Marcus has already
> > provided
> > a sketch of some of it, so I'll do that one last. :)
> > 
> > Regarding #1:
> > Off list, Jeff requested that the runtime be fixed to correct tag
> > propagation for block that change their relative rate.  My initial
> > response was not to bother trying, since the runtime doesn't have
> > enough information - only the block itself can perform correct tag
> > propagation.
> > 
> > However, if we allow blocks that change their relative rate to give
> > the
> > runtime more information about the rate change, then the runtime
> > can
> > actually do most of the work for tag propagation.
> > 
> > For some background, my latest pull request for a tag propagation
> > fix
> > made these relevant changes:
> > 
> > 1. Modified or added these API methods:
> > 
> >      gr::block::set_relative_rate(double relative_rate);
> >      gr::block::set_relative_rate(uint64_t interpolation, uint64_t
> > decimation);
> >      gr::block::set_inverse_relative_rate(double
> > inverse_relative_rate);
> > 
> > 2. Changed the tag offset propagation arithmetic to use multiple
> > precision integer rationals:
> > 
> >       ...
> >       static const mpq_class one_half(1, 2);
> >       ...
> >            else {
> >              mpz_class offset;
> >              for(t = rtags.begin(); t != rtags.end(); t++) {
> >                tag_t new_tag = *t;
> >                offset = new_tag.offset * mp_rrate + one_half;
> >                new_tag.offset = offset.get_ui();
> >                out_buf->add_item_tag(new_tag);
> >              }
> >            }
> >       ...
> > 
> > 
> > The expression
> > 
> >     offset = new_tag.offset * mp_rrate + one_half;
> > 
> > can be viewed as a degenerate case of a more general expression
> > 
> >     offset = (new_tag.offset - rr_in_offset) * mp_rrate +
> > rr_out_offset + one_half;
> > 
> > Where rr_in_offset is the input sample offset where the particular
> > mp_rrate value is first valid, and rr_out_offset is the output
> > sample
> > offset where the particular mp_rrate value is first valid.
> > 
> > The runtime currently assumes these rr_(in|out)_offset values are
> > always 0.
> > 
> > So the solution, at a high level, is for the blocks performing
> > relative
> > rate changes to provide values for rr_in_offset and rr_out_offset
> > along
> > with every change to the relative rate.  Then the runtime can take
> > care
> > of the rest of the tag propagation headaches.
> > 
> > So the API for setting relative rate then becomes:
> > 
> >     gr::block::set_relative_rate(double relative_rate, uint64_t
> > in_offset = 0, uint64_t out_offset = 0);
> >     gr::block::set_relative_rate(uint64_t interpolation, uint64_t
> > decimation, uint64_t in_offset = 0, uint64_t out_offset = 0);
> >     gr::block::set_inverse_relative_rate(double
> > inverse_relative_rate, uint64_t in_offset = 0, uint64_t out_offset
> > = 0);
> > 
> > But since the runtime would now maintian a dynamic structure of
> > (relative rate, in offset, out offset) tuples, the external API for
> > getting relative rate gets a little messy/ambiguous.  I'm not sure
> > what
> > to do about that yet.
> > 
> > This concept can support blocks that change their relative rate
> > with
> > every output sample, such as the PFB clock sync blocks and the
> > symbol
> > synchronizer blocks.
> > 
> > I suppose I'll test it with the symbol synchronizer blocks, since I
> > now
> > see that they don't do correct tag propagation if their output rate
> > is
> > set to anything higher than 1 sample/symbol. :P
> > 
> > Regards,
> > Andy
> > 
> 
> 



reply via email to

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