What drives noutput_items passed to forecast?

Hi all,

I understand the basics that forecast is ensuring the number of input
items exist to produce a certain number of output items, but what
exactly drives the number of output items that are passed to forecast()?
What drives the scheduler to select this number?

For example, if I run benchmark_rx.py and monitor noutput_items in
gr_clock_recovery_mm_ff.cc, it looks like this:
http://cyprus.cmcl.cs.cmu.edu/tmp/clockr_forecast

But, what drives this noutput_items parameter decision?

Is the scheduler in an iterative process where, with an exponential
decay, it asks: “How many input items do i need to produce
noutput_items?” … starting at 2^13, which I’m assuming is some sort of
maximum buffer size?

Then, if it does not have enough items, it decreases the noutput_items
it is passing exponentially, and asks again… until it has enough input
items, then calls work().

Thanks!
George

On Wed, Feb 27, 2008 at 06:21:17PM -0500, George N. wrote:

Thanks!
George

For blocks derived from gr_sync_block, gr_sync_interpolator and
gr_sync_interpolator the scheduler knows how to compute noutputs from
ninputs and vice versa, and thus chooses noutputs so as to maximize
the amount of data given to work subject to all other constraints.

For other blocks, there isn’t a mechanism for mapping from ninputs to
noutputs, so it does a binary search calling forecast until it finds
the value that processes the most input subject to all other
constraints.

The details are in gr_single_threaded_scheduler.cc

The two basic constraints are:

how much input is available
how much output space is available

There are additional constraints based on output_multiple, etc.

Eric

Eric B. wrote:

The details are in gr_single_threaded_scheduler.cc

The two basic constraints are:

how much input is available
how much output space is available

There are additional constraints based on output_multiple, etc.

I’m trying to emulate buffers and call general_work() for
gr_clock_recovery_mm_ff. I’m 99.99% sure that its output_multiple is 1.

I have a certain number of input items, and I start probing for
noutput_items by starting at 8192 and cutting it in half each time
forecast() tells me I need more input than I actually have.

Once I find an appropriate noutput_items, I pass the input with the
total number of input items and noutput_items.

Instead of returning noutput_items from the block, I return ‘ii’, which
is the value that would have been passed to consume(). I then remove
this number of items from my input and use whats left to probe again
until I reach noutput_items=1 and the total required input is greater
than the input I have left.

But after a short while ‘ii’ becomes some really odd number such as
-2147483646… this obviously kills everything because consuming a
negative number is bad.

Is there some other constraint that is less obvious? I’m using 16-byte
aligned buffers, calling forecast() to ensure that what it returns is <=
to the total input I have, and then call general_work.

I know I’m totally hacking around the system, but I’d appreciate any
help if there’s something obvious I’m missing.

Thanks!
George

George N. wrote:

I’m trying to emulate buffers and call general_work() for
is the value that would have been passed to consume(). I then remove
to the total input I have, and then call general_work.

I know I’m totally hacking around the system, but I’d appreciate any
help if there’s something obvious I’m missing.

I think I’ve got it… it doesn’t enjoy when the number of input items
needed is around equal to the total number of input items (~6 off or
so).

  • George

Eric B. wrote:

Eric

From what I could tell, the clock recovery block does not use a
history. I dug through the code and couldn’t find a related
set_history().

  • George

On Sat, Mar 01, 2008 at 06:59:04PM -0500, George N. wrote:

I think I’ve got it… it doesn’t enjoy when the number of input items
needed is around equal to the total number of input items (~6 off or so).

It sounds like you’re not handling history properly.

Do you initialize your remimplementation of the scheduler such that
the buffers are initialized with history() - 1 zeros?

Eric