Scheduler Help/Question

I have a question about the scheduling of work.

In ‘gr_single_threaded_scheduler.cc’, I changed the pound-def
ENABLE_LOGGING
from 0 to 1.
I did a ‘make’ and then a ‘make install’.
However, when I execute my flow graph, the log file is not generated.

Is this not the file of interest to investigate the work scheduling?

I am also wondering about the condition to set ‘making_progress’ to
true.
Right now it looks for the number of outputs produced to be greater than
0.
Should the condition be: ( ( num_produced > 0 ) OR ( num_consumed > 0 )
) ?

Imagine a block that has two states of operation. In a SCAN state, the
block
does not output anyway, but rather is looking at the input data for some
kind of trigger event. In a EVENT state, the block will have a 1-to-1
input
to output function until it goes back into the SCAN state.
With this kind of block, ‘making_progress’ will false during the SCAN
state.
With the purposed condition, we would make progress.
Is there any reasons that my thinking is wrong??

Thanks in advance,
EF

View this message in context:
http://www.nabble.com/Scheduler-Help-Question-tp21223608p21223608.html
Sent from the GnuRadio mailing list archive at Nabble.com.

On Wed, Dec 31, 2008 at 05:41:16AM -0800, Earle F. wrote:

I have a question about the scheduling of work.

In ‘gr_single_threaded_scheduler.cc’, I changed the pound-def ENABLE_LOGGING
from 0 to 1.
I did a ‘make’ and then a ‘make install’.
However, when I execute my flow graph, the log file is not generated.

Is this not the file of interest to investigate the work scheduling?

Which source are you working with? the trunk, or one of the tarballs?

The trunk is using the “thread-per-block” scheduler by default, so
if you’re using that, enabling logging in
gr_single_threaded_scheduler.cc won’t make any difference.

For the thread-per-block scheduler, see runtime/gr_tpb_.{h,cc}

I am also wondering about the condition to set ‘making_progress’ to true.
Right now it looks for the number of outputs produced to be greater than 0.
Should the condition be: ( ( num_produced > 0 ) OR ( num_consumed > 0 ) ) ?

That would probably make more sense, but I’m not sure that it matters
too much in reality. If you try it out, let us know.

FWIW, the TPB code, gr_block_executor::run_one_iteration, handles the
situation you mention by returning the state READY_NO_OUTPUT.

Imagine a block that has two states of operation. In a SCAN state, the block
does not output anyway, but rather is looking at the input data for some
kind of trigger event. In a EVENT state, the block will have a 1-to-1 input
to output function until it goes back into the SCAN state.
With this kind of block, ‘making_progress’ will false during the SCAN state.
With the purposed condition, we would make progress.
Is there any reasons that my thinking is wrong??

Thanks in advance,
EF

FYI, if you’re using the code in the trunk, you can select the
scheduler used at runtime by setting the GR_SCHEDULER environment
variable. E.g.,

$ GR_SCHEDULER=TPB ./my-gnuradio-application.py …

or

$ GR_SCHEDULER=STS ./my-gnuradio-application.py …

Eric

Okay I am using the default scheduler. So now I have enabled the logging
for
the appropriate thread-per-block scheduler files.

Here’s the heart of my problem. My flow graph has five blocks, A, B, C,
D,
E.
Output of A is input to B and C.
Output of C is input to D.
Output of B and D are input to E.

Block A is a file source.

Block B has a 1-to-1 input to output function.

Block C breaks the samples from A into partitions of N samples. The
block
does its function over the N samples. Then it outputs the resulting N
values.

Block D looks at the input and produces an enable signal. The curious
feature, due to implementation, is that this block will only output the
enable signal high once it detects the enable going back low.

Block E takes the inputs from B and D and only outputs the values of B
when
D (the enable) is high.

Running this flow graph hangs. Looking at the log files produced for
each
block I see that blocks A & B are BLKD_OUT and blocks C, D & E are
BLKD_IN.

In this scenario, an enable signal will exist over a partition boundary,
say
starts at N-10 and ends at N+10.

At the point of hanging:
Block A has produced N values.
Block B has consumed N values and produced N values.
Block C has consumed N values and produced N values.
Block D has consumed N values and produced N-10 values.
Block E has consumed N-10 values.

If only block A would produce the next N values the system would chug
along.
To those smarter than I, is there anything obvious as to why this is
stalling the flow graph?
How does the buffers work in this case?
Block C’s input buffer is empty and ready.
Block B has 10 values left in it’s output buffer, but shouldn’t it be
able
to produce more outputs?

Thanks again in advance,
EF


View this message in context:
http://www.nabble.com/Scheduler-Help-Question-tp21223608p21236789.html
Sent from the GnuRadio mailing list archive at Nabble.com.

On Wed, Dec 31, 2008 at 12:32:45PM -0800, Earle F. wrote:

Block A is a file source.

Block E takes the inputs from B and D and only outputs the values of B when
D (the enable) is high.

The bug is that D should always produce an enable output, 1:1 with the
input. If you’re not sure of the state at start up time, output a
reasonable default value.

Running this flow graph hangs. Looking at the log files produced for each
block I see that blocks A & B are BLKD_OUT and blocks C, D & E are BLKD_IN.

What’s happening is that the buffer between B & E is filling, then
between A & B fills, then A blocks and the everything hangs because D
isn’t outputting the enable/not-enable signal.

If only block A would produce the next N values the system would chug along.
To those smarter than I, is there anything obvious as to why this is
stalling the flow graph?
How does the buffers work in this case?
Block C’s input buffer is empty and ready.
Block B has 10 values left in it’s output buffer, but shouldn’t it be able
to produce more outputs?

Thanks again in advance,
EF

Eric

Eric B. wrote:

The bug is that D should always produce an enable output, 1:1 with the
input. If you’re not sure of the state at start up time, output a
reasonable default value.

I guess I would agree with your 1:1 statement if I was using a
gr_sync_block. And I may not have previously said this, but I am using
a
gr_block. My understanding of the gr_block does not need a 1:1
input:output.
Is that incorrect?

My block D can not always produce an enable output. Block D must see
the
complete event occur. Then the block determines if the event was a
valid
event. This can only be determined after the event is finished. At
that
time if Block D sees a valid event, then the enable signal is output
high
for the time matching the event. Otherwise the block outputs low for
that
time.

With this operation of block D, is it not possible to work in the
framework
of GNURadio?


View this message in context:
http://www.nabble.com/Scheduler-Help-Question-tp21223608p21310592.html
Sent from the GnuRadio mailing list archive at Nabble.com.

On Tue, Jan 6, 2009 at 5:43 AM, Earle F. [email protected]
wrote:

My block D can not always produce an enable output. Block D must see the
complete event occur. Then the block determines if the event was a valid
event. This can only be determined after the event is finished. At that
time if Block D sees a valid event, then the enable signal is output high
for the time matching the event. Otherwise the block outputs low for that
time.

With this operation of block D, is it not possible to work in the framework
of GNURadio?

I’m not convinced Eric’s analysis is correct, but that would only be
because I don’t think there is enough information in your description
to accurately determine the problem. There is no reason, however,
from what you’ve described, that it shouldn’t be possible to implement
in GNU Radio. Without looking at the actual code, we can’t tell
whether there is a topology problem, a bug in the assumptions that a
work function is making, or something else.

What I suspect is that you need to introduce a sample delay on one of
the paths to match the pipeline delay of block D. That way the two
streams converge on the final block at the right “time”. Block E
probably makes the assumption that it needs to consume equal amounts
of items on each input; if one leg has more pipeline delay, the
scheduler will be looking for it to produce more samples to match the
number of samples consumed from the other leg.

But this is just a hunch based on what I’ve heard so far.

-Johnathan

On Tue, Jan 06, 2009 at 05:43:40AM -0800, Earle F. wrote:

gr_sync_block. And I may not have previously said this, but I am using a
With this operation of block D, is it not possible to work in the framework
of GNURadio?

What you’re trying to do requires unbounded memory in the worst case.
Perhaps you should consider another way to organize your computation?

Eric

Eric B. wrote:

What you’re trying to do requires unbounded memory in the worst case.
Perhaps you should consider another way to organize your computation?

But this isn’t happening in my scenario. If necessary, I can add an
event
timeout or maximum size event value to prevent this infinite memory
requirement.

Reminder of my scenario:

In this scenario, an enable signal will exist over a partition boundary,
say starts at N-10 and ends at N+10.

At the point of hanging:
Block A has produced N values.
Block B has consumed N values and produced N values.
Block C has consumed N values and produced N values.
Block D has consumed N values and produced N-10 values.
Block E has consumed N-10 values.

Block D just needs 10 more samples from block C for fully see the event,
which cause the enable signal to be produced. But block C has consumed
all
it’s inputs to produced as many outputs as possible. So block C just
needs
block A to output samples.

The question is, why does block A not produce samples (we have not
reached
EOF)?
The input buffer to block B & C are both empty, so shouldn’t block A be
able
to produce outputs?
Block B still has 10 samples left in it’s output buffer. Is that
preventing
block B from receiving inputs?

Thanks
EF

View this message in context:
http://www.nabble.com/Scheduler-Help-Question-tp21223608p21357532.html
Sent from the GnuRadio mailing list archive at Nabble.com.

Eric B. wrote:

Let’s say that block D never produces an output, but is consuming all
of it’s input. Can you see how this leads to a hang?

I can see that will cause the flow graph to hang. And I followed your
explanation.
I have added a “timeout” feature to block D, so that after a maximum of
M
samples, block D will output the appropriate enable signal.
So now it is impossible for block D to consume all inputs and never
produce
an output.

Let me further describe my test:
Let N=100, M=40.
The expected enable signal out of block D is:
0 for n=0 to 49
1 for n=50 to 79
0 for n=80 to 89
1 for n=90 to 109
0 for n=110 to 199

Block A produce 100 samples to it’s output buffer.
Block B consumed all 100 samples of it’s input and produced 100 samples
to
it’s output buffer.
Block C consumed all 100 samples of it’s input and produced 100 samples
to
it’s output buffer.

Block D consumed all 100 samples of it’s input and produced the correct
enable signal for n=0 to 89.
The state inside block D is now 10, because it saw the beginning of an
event
from n=90 to 99. It is waiting for the event to end or for the state to
reach M=40.

Block E consumed 90 input samples from the input buffer from B and from
the
input buffer from D to produce 30 outputs. These outputs are simply the
values from block B at n=50 to 79.

Eric B. wrote:

It goes like this. E ends up BLKD_IN on it’s second input, but
meanwhile the buffer on it’s first input is full. It’s full because B
has been writing it as quickly as it can. Once E’s first input buffer
(== B’s output buffer) is full. B becomes output blocked. It will
never run again because it’s got nowhere to put it’s output.

Shouldn’t the output buffer be nearly empty for block B now? Block E has
consumed 90 of the 100 samples from block B.
Shouldn’t block B be able to process another 90 samples or even 100
samples
(assuming the output buffer is big enough)?

Why doesn’t block A produce the next 100 samples to it’s output buffer?
And
if it does, why doesn’t block C consumed those 100 samples? And also,
why
doesn’t block B consume at least 90 of those 100 samples??

Thanks again for all the insight
EF


View this message in context:
http://www.nabble.com/Scheduler-Help-Question-tp21223608p21360594.html
Sent from the GnuRadio mailing list archive at Nabble.com.

On Wed, Dec 31, 2008 at 12:32:45PM -0800, Earle F. wrote:

Starting back at the problem description…

Block E takes the inputs from B and D and only outputs the values of B when
D (the enable) is high.

Running this flow graph hangs. Looking at the log files produced for each
block I see that blocks A & B are BLKD_OUT and blocks C, D & E are BLKD_IN.

In this scenario, an enable signal will exist over a partition boundary, say
starts at N-10 and ends at N+10.

At the point of hanging:

Let’s say that block D never produces an output, but is consuming all
of it’s input. Can you see how this leads to a hang?

It goes like this. E ends up BLKD_IN on it’s second input, but
meanwhile the buffer on it’s first input is full. It’s full because B
has been writing it as quickly as it can. Once E’s first input buffer
(== B’s output buffer) is full. B becomes output blocked. It will
never run again because it’s got nowhere to put it’s output.

B and C both read from A’s output 0 output buffer (it’s single-writer,
dual-reader buffer (A writes, B & C read)). C could still run (it it
had input), since D’s draining its output. A’s buffer does fill up
however, because B is no longer able to run, and thus A’s buffer does
not empty. The fact that C is reading is necessary but not sufficent
to drain A. Both B and C need to be consuming A’s output, but B is
output blocked.

Does this make sense? This is where my comment about needing an
unbounded amount of memory in the worst case comes from.

In your case, the question is how long can D go without producing an
output before the hang occurs? Given long enough, it will hang.
The answer is based on the size of the buffers between the blocks.
Although not specified and not part of any advertised contract,
subject to change on a whim, … the buffers are typically about
32KB…

Eric

On Thu, Jan 08, 2009 at 12:44:18PM -0800, Earle F. wrote:

samples, block D will output the appropriate enable signal.
0 for n=110 to 199
from n=90 to 99. It is waiting for the event to end or for the state to

meanwhile the buffer on it’s first input is full. It’s full because B
Why doesn’t block A produce the next 100 samples to it’s output buffer? And
if it does, why doesn’t block C consumed those 100 samples? And also, why
doesn’t block B consume at least 90 of those 100 samples??

Thanks again for all the insight
EF

Doesn’t C do a set_output_multiple(N(==100))? If so, and there’s only
90
samples available it won’t run.

You’re on your own from here.

This is K7GNU, clear.
Eric