discuss-gnuradio
[Top][All Lists]
Advanced

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

Re: [Discuss-gnuradio] Understanding processing delay


From: Veljko Pejovic
Subject: Re: [Discuss-gnuradio] Understanding processing delay
Date: Fri, 23 Oct 2015 13:47:38 +0200

Thanks for a nice explanation Marcus,

Under the assumption that samples are taken one by one from the
source, and passed one by one to each consecutive block, I was
expecting to see that the probe at the source shows a number which is
equal to 2 + the value of the probe at the end. My weak intuition was
- while the source is firing one sample, the first adder is finishing
the processing of the previous sample, while the second added is
finishing the processing of the sample before that one.

I didn't count on buffering and parallel processing (which explains
non-deterministic behaviour, as well).

Regards,

Veljko


On Wed, Oct 21, 2015 at 12:11 PM, Marcus Müller
<address@hidden> wrote:
> Hi Veljko,
>
> GNU Radio works by calling your blocks' "work" methods with buffers full of
> consecutive items (read: samples). These blocks might then run in parallel.
> For example, assume that the first add_const has worked through samples
> 0-999, the second is called with the resulting 1000 items, while the first
> already starts to consume the 1000-1999 item coming from your source.
> The probe block always takes the last item it gets in such an item chunk and
> memorizes it. Since these chunk sizes need not be constant, and processing
> is timing-wise totally unconnected to when you query the probes, it might be
> totally random what you're seeing.
>
> So the interesting point here is: what were you *hoping* to find out with
> your flow graph?
>
> Now, the subject line of your mail suggests you want to find out how long it
> takes for samples to propagate from source to sink -- I'd recommend using
> the "ctrlport monitor" to figure out how long the average calls to work
> lasted, and how many samples the work functions processed on average --
> that'll tell you something like "for 4096, on average, my block needed
> 200µs". You could divide that down to give you a "latency per sample", but
> honestly, considering that you never process individual samples in GNU
> Radio, that would be meaningless, and also misleading, because it'd hide the
> "chunky" processing behaviour.
>
> Best regards,
> Marcus
>
>
> On 20.10.2015 18:37, Veljko Pejovic wrote:
>
> Hi,
>
> In order to better understand the gnuradio flowgraph I created a very
> simple test in which I connected a vector source (running through
> 1,2,3,4,5,6,7,8,9,0) in series with two “Add Const” blocks. The first
> block adds 1, the second subtracts 1. I have two probes that I query
> every second. One probe is connected directly to the vector source,
> the other to the output of the second “Add Const” block. I print the
> output of both probes every second. This is what I get from one run
> (printing probe at the end, followed by the probe at the source):
>
> $ python test_delay.py
> 0.0 0.0
> Press Enter to quit: 2.0 5.0
> 5.0 9.0
> 7.0 2.0
> 2.0 6.0
> 4.0 8.0
> 0.0 2.0
> 4.0 7.0
> 8.0 1.0
> 0.0 5.0
> 0.0 3.0
> 8.0 1.0
> 4.0 8.0
> 4.0 9.0
> 8.0 1.0
> 0.0 4.0
> 7.0 0.0
> 6.0 9.0
> 5.0 8.0
> 3.0 6.0
> 5.0 8.0
> 8.0 2.0
> 3.0 4.0
> 8.0 3.0
>
> and so on.
>
> Two things surprise me here:
> 1) The output is different every time I run the graph.
> 2) The difference between the probe at the end of the second "Add
> Const" element and the probe at the vector source is not constant. See
> for example pairs: 0.0,2.0 , 0.0,5.0 and 0.0,3.0 all of which can be
> seen in the output.
>
> Can someone please explain this non-deterministic behaviour?
>
> Thanks,
>
> Veljko
>
> p.s. attached is a screenshot of the GRC file I started from, and
> here's the python code (slightly modified from the GRC):
>
> from gnuradio import eng_notation
> from gnuradio import gr
> from gnuradio.eng_option import eng_option
> from gnuradio.filter import firdes
> from optparse import OptionParser
> import threading
> import time
>
> class test_delay(gr.top_block):
>
>     def __init__(self):
>         gr.top_block.__init__(self, "Test Delay")
>
>         self.variable_function_probe_0 = variable_function_probe_0 = 0
>         self.samp_rate = samp_rate = 1
>
>         self.probe = blocks.probe_signal_f()
>         self.probe_src = blocks.probe_signal_f()
>         def _variable_function_probe_0_probe():
>             while True:
>                 val = self.probe.level()
>                 val_src = self.probe_src.level()
>                 print val, val_src
>                 try:
>                     self.set_variable_function_probe_0(val)
>                 except AttributeError:
>                     pass
>                 time.sleep(1.0 / (1))
>         _variable_function_probe_0_thread =
> threading.Thread(target=_variable_function_probe_0_probe)
>         _variable_function_probe_0_thread.daemon = True
>         _variable_function_probe_0_thread.start()
>         self.blocks_vector_source_x_0 = blocks.vector_source_f((1, 2,
> 3, 4, 5, 6, 7, 8, 9, 0), True, 1, [])
>         self.blocks_add_const_vxx_1 = blocks.add_const_vff((-1, ))
>         self.blocks_add_const_vxx_0 = blocks.add_const_vff((1, ))
>
>         self.connect((self.blocks_add_const_vxx_0, 0),
> (self.blocks_add_const_vxx_1, 0))
>         self.connect((self.blocks_add_const_vxx_1, 0), (self.probe, 0))
>         self.connect((self.blocks_vector_source_x_0, 0),
> (self.blocks_add_const_vxx_0, 0))
>         self.connect((self.blocks_vector_source_x_0, 0), (self.probe_src,
> 0))
>
>     def get_variable_function_probe_0(self):
>         return self.variable_function_probe_0
>
>     def set_variable_function_probe_0(self, variable_function_probe_0):
>         self.variable_function_probe_0 = variable_function_probe_0
>
>     def get_samp_rate(self):
>         return self.samp_rate
>
>     def set_samp_rate(self, samp_rate):
>         self.samp_rate = samp_rate
>
> if __name__ == '__main__':
>     parser = OptionParser(option_class=eng_option, usage="%prog: [options]")
>     (options, args) = parser.parse_args()
>     tb = test_delay()
>     tb.start()
>     try:
>         raw_input('Press Enter to quit: ')
>     except EOFError:
>         pass
>     tb.stop()
>     tb.wait()
>
>
>
> _______________________________________________
> Discuss-gnuradio mailing list
> address@hidden
> https://lists.gnu.org/mailman/listinfo/discuss-gnuradio
>
>
>
> _______________________________________________
> Discuss-gnuradio mailing list
> address@hidden
> https://lists.gnu.org/mailman/listinfo/discuss-gnuradio
>



reply via email to

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