discuss-gnuradio
[Top][All Lists]
Advanced

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

Re: GNU Radio 3.9.3.0 Python basic block - issues with forecast and prod


From: Johannes Demel
Subject: Re: GNU Radio 3.9.3.0 Python basic block - issues with forecast and produce
Date: Sat, 22 Jan 2022 12:25:59 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.14.0

Hi Patric,

since your goal is to produce a variable number of output items, your `general_work` approach seems to be the correct one. I mean "variable number of output items" in the sense that there is no fixed relation between the number of input items to the number of output items. Just for reference.

`WORK_CALLED_PRODUCE` is one of those "magic values" that are defined somewhere in the system. I've never personally used it in any block.

It is documented here:
https://www.gnuradio.org/doc/doxygen/classgr_1_1block.html

The function is found here:
https://www.gnuradio.org/doc/doxygen/classgr_1_1block.html#aa5581727d057bdd8113f8b2a3fc5bd66

I use `bpython3` to explore Python methods etc. In your case, I expect that `self.WORK_CALLED_PRODUCE` should be available.

BUT: Don't use `produce`! In your case use:
`return self.buffer_len`

Why? Because the all the buffer pointer updates will be handled after you return from `general_work`. The `produce` method exists for cases where you have multiple output buffers and want to produce different numbers of output items. e.g 5 samples on `output_items[0]` and 25 samples on `output_items[1]`.

In your case, you `return 0` which tells the scheduler that you did not produce any items.

More generally, try to minimize calls to `consume`/`produce`. Keep track of the number of samples your `general_work` consumes and how many samples you've written to your output buffer. At the end of `general_work` report these values to the system:
- consumed items via `consume_each`
- produced items via `return integer_with_number_of_consumed_items`.

The `forecast` method expects estimates. The scheduler will call `general_work` anyways at some point, if the system is unable to fulfill your forecast requirement. `set_output_multiple` is much more strict.
In your case I'd start with:
`ninput_items_required[0] = noutput_items`
which might be inefficient. But you can update it with better forecasts later. Talking about efficiency: I'd only worry about efficiency in C++ blocks. Python blocks incur quite a penalty.

Cheers
Johannes

On 21.01.22 15:14, Patric Müller wrote:
Hello everyone,

I am currently trying to create a basic block similar to this issue:
https://stackoverflow.com/questions/68289222/gnu-radio-buffer-size

Some software and hardware info:
GNU Radio version: 3.9.3.0
Python version: 3.9.7
OS: Ubuntu 20.04

I always want to work on the same number of items, say 1024. Now I would like to use up all of the items, but I want to produce something between say 500 - 1500 items. For now, I would like to create a simple block with one input and one output, which consumes a set number of items and outputs only a fraction of those incoming items in order to understand it better.

Therefore I started with a general block and wanted to change ninput_items_required[0]. However, ninput_items_required is an integer. Trying to directly change this integer values results in:

Unable to cast Python instance to C++ type (compile in debug mode for details)


My second question is about the produce() function. If it is used, general_work() should return
WORK_CALLED_PRODUCE
but how exactly? After calling produce() and telling the scheduler how many items are produced, can I then change output_items[0]?

My attempt at the forecast() function and general_work() is provided below. General suggestions/hints or a basic example would be helpful and immensely appreciated. If additional background is required, let me know and I will gladly provide more information.


     def forecast(self, noutput_items, ninput_items_required):
        # Estimate, that we will always need self.buffer_len items on input port [0]
         ninput_items_required[0] = self.buffer_len


     def general_work(self, input_items, output_items):
         # Firstly check, if input_items has a sufficient amount of items
         if len(input_items[0]) >= self.buffer_len:
             # Then consume exactly self.buffer_len items on input_port[0]
             self.consume(0, self.buffer_len)
            # Now I would like to only output a fraction of the input items
             # say the first self.out_items, on output port[0]
             self.produce(0, self.out_items)
             # Do I set my output_items[0] here?
         # Now I only need to return WORK_CALLED_PRODUCE, but how exactly?
         return 0


Kind regards,
Patric Müller






reply via email to

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