Re: How to balance workload among cores? Laptop cannot keep up with the USRP2 data flow

  • *CPU scheduling is generally the responsibility of the operating system
  • *kernel, NOT Gnu Radio. What Gnu Radio does is schedule
    blocks to threads, and the execution of those threads, and CPU
    assignment is up to the kernel. In general, the kernel does a good
    job of CPU scheduling.
  • *Your problem is probably that your flow-graphs aren’t optimal in some
  • *way, and thus take more system resources than they should.
    Yes, I do not why it takes a lot of resources alhough I can see with
    gkrellm application that my CPUs are about 50-60%, so it is not so
    bad.
  • *The other issue may be your GiGE network interface might be one that
  • *isn’t very good in the buffering department, and thus makes the
    • system work much harder than it should handling continuous packet
  • *traffic.
  • *What bandwidth are you using? (That is, what decimation/interpolation
  • *are you using)?
    I am using 30,76Mbps in the transmitter (USRP interpolation sink 104)
    I am using 6,25Mbps in the receiver (USRP decimation source 512)
  • *You haven’t shared much in the way of details about your flow-graph, and
  • *I suspect that’s where your problem lies.
    I can post my .py file which is:
    from gnuradio import audio
    from gnuradio import blks2
    from gnuradio import gr
    from gnuradio import usrp2
    from gnuradio.eng_option import eng_option
    from gnuradio.gr import firdes
    from gnuradio.wxgui import forms
    from grc_gnuradio import wxgui as grc_wxgui
    from optparse import OptionParser
    import wx

class top_block(grc_wxgui.top_block_gui):

def init(self):
grc_wxgui.top_block_gui.init(self, title=“Top Block”)

##################################################
# Variables
##################################################
self.tune_osc_dem = tune_osc_dem = 94000000
self.tune_filter = tune_filter = 75000
self.samp_rate = samp_rate = 32000
self.fm_freq_mod = fm_freq_mod = 94000000

##################################################
# Controls
##################################################
_tune_osc_dem_sizer = wx.BoxSizer(wx.VERTICAL)
self._tune_osc_dem_text_box = forms.text_box(
  parent=self.GetWin(),
  sizer=_tune_osc_dem_sizer,
  value=self.tune_osc_dem,
  callback=self.set_tune_osc_dem,
  label="Tunned frequency demodulator",
  converter=forms.float_converter(),
  proportion=0,
)
self._tune_osc_dem_slider = forms.slider(
  parent=self.GetWin(),
  sizer=_tune_osc_dem_sizer,
  value=self.tune_osc_dem,
  callback=self.set_tune_osc_dem,
  minimum=88000000,
  maximum=108000000,
  num_steps=800,
  style=wx.SL_HORIZONTAL,
  cast=float,
  proportion=1,
)
self.Add(_tune_osc_dem_sizer)
_tune_filter_sizer = wx.BoxSizer(wx.VERTICAL)
self._tune_filter_text_box = forms.text_box(
  parent=self.GetWin(),
  sizer=_tune_filter_sizer,
  value=self.tune_filter,
  callback=self.set_tune_filter,
  label="LPF Cutoff Freq",
  converter=forms.float_converter(),
  proportion=0,
)
self._tune_filter_slider = forms.slider(
  parent=self.GetWin(),
  sizer=_tune_filter_sizer,
  value=self.tune_filter,
  callback=self.set_tune_filter,
  minimum=15000,
  maximum=150000,
  num_steps=1000,
  style=wx.SL_HORIZONTAL,
  cast=float,
  proportion=1,
)
self.Add(_tune_filter_sizer)
_fm_freq_mod_sizer = wx.BoxSizer(wx.VERTICAL)
self._fm_freq_mod_text_box = forms.text_box(
  parent=self.GetWin(),
  sizer=_fm_freq_mod_sizer,
  value=self.fm_freq_mod,
  callback=self.set_fm_freq_mod,
  label="FM frequency modulator",
  converter=forms.float_converter(),
  proportion=0,
)
self._fm_freq_mod_slider = forms.slider(
  parent=self.GetWin(),
  sizer=_fm_freq_mod_sizer,
  value=self.fm_freq_mod,
  callback=self.set_fm_freq_mod,
  minimum=0,
  maximum=110000000,
  num_steps=300,
  style=wx.SL_HORIZONTAL,
  cast=float,
  proportion=1,
)
self.Add(_fm_freq_mod_sizer)

##################################################
# Blocks
##################################################
self.audio_sink_0 = audio.sink(32000, "plughw:0,0", True)
self.blks2_fm_demod_cf_0 = blks2.fm_demod_cf(
  channel_rate=320000,
  audio_decim=10,
  deviation=75000,
  audio_pass=1000,
  audio_stop=16000,
  gain=20.0,
  tau=75e-6,
)
self.blks2_rational_resampler_xxx_0_0 = 

blks2.rational_resampler_fff(
interpolation=5,
decimation=1,
taps=None,
fractional_bw=None,
)
self.blks2_rational_resampler_xxx_1 = blks2.rational_resampler_fff(
interpolation=4,
decimation=1,
taps=None,
fractional_bw=None,
)
self.blks2_rational_resampler_xxx_1_0_0 =
blks2.rational_resampler_ccc(
interpolation=100,
decimation=61,
taps=None,
fractional_bw=None,
)
self.gr_frequency_modulator_fc_0 = gr.frequency_modulator_fc(0.980)
self.gr_multiply_const_vxx_1 = gr.multiply_const_vcc((32000, ))
self.gr_wavfile_source_0 =
gr.wavfile_source(“/home/jorge/Desktop/outfile2.wav”, True)
self.low_pass_filter_0 = gr.fir_filter_ccf(1, firdes.low_pass(
3, 320000, tune_filter, 5000, firdes.WIN_HAMMING, 6.76))
self.low_pass_filter_0_0 = gr.interp_fir_filter_fff(1,
firdes.low_pass(
1, 240000, 18e3, 2e3, firdes.WIN_HAMMING, 6.76))
self.usrp2_sink_xxxx_0 = usrp2.sink_32fc()
self.usrp2_sink_xxxx_0.set_interp(104)
self.usrp2_sink_xxxx_0.set_center_freq(fm_freq_mod)
self.usrp2_sink_xxxx_0.set_gain(0)
self.usrp2_source_xxxx_0 = usrp2.source_32fc()
self.usrp2_source_xxxx_0.set_decim(512)
self.usrp2_source_xxxx_0.set_center_freq(tune_osc_dem)
self.usrp2_source_xxxx_0.set_gain(10)

##################################################
# Connections
##################################################
self.connect((self.gr_frequency_modulator_fc_0, 0),

(self.gr_multiply_const_vxx_1, 0))
self.connect((self.blks2_rational_resampler_xxx_0_0, 0),
(self.low_pass_filter_0_0, 0))
self.connect((self.low_pass_filter_0_0, 0),
(self.blks2_rational_resampler_xxx_1, 0))
self.connect((self.gr_wavfile_source_0, 0),
(self.blks2_rational_resampler_xxx_0_0, 0))
self.connect((self.blks2_rational_resampler_xxx_1, 0),
(self.gr_frequency_modulator_fc_0, 0))
self.connect((self.usrp2_source_xxxx_0, 0),
(self.blks2_rational_resampler_xxx_1_0_0, 0))
self.connect((self.blks2_fm_demod_cf_0, 0), (self.audio_sink_0, 0))
self.connect((self.blks2_rational_resampler_xxx_1_0_0, 0),
(self.low_pass_filter_0, 0))
self.connect((self.low_pass_filter_0, 0), (self.blks2_fm_demod_cf_0,
0))
self.connect((self.gr_multiply_const_vxx_1, 0),
(self.usrp2_sink_xxxx_0, 0))

def set_tune_osc_dem(self, tune_osc_dem):
self.tune_osc_dem = tune_osc_dem
self._tune_osc_dem_slider.set_value(self.tune_osc_dem)
self._tune_osc_dem_text_box.set_value(self.tune_osc_dem)
self.usrp2_source_xxxx_0.set_center_freq(self.tune_osc_dem)

def set_tune_filter(self, tune_filter):
self.tune_filter = tune_filter
self.low_pass_filter_0.set_taps(firdes.low_pass(3, 320000,
self.tune_filter, 5000, firdes.WIN_HAMMING, 6.76))
self._tune_filter_slider.set_value(self.tune_filter)
self._tune_filter_text_box.set_value(self.tune_filter)

def set_samp_rate(self, samp_rate):
self.samp_rate = samp_rate

def set_fm_freq_mod(self, fm_freq_mod):
self.fm_freq_mod = fm_freq_mod
self._fm_freq_mod_slider.set_value(self.fm_freq_mod)
self._fm_freq_mod_text_box.set_value(self.fm_freq_mod)
self.usrp2_sink_xxxx_0.set_center_freq(self.fm_freq_mod)

if name == ‘main’:
parser = OptionParser(option_class=eng_option, usage=“%prog:
[options]”)
(options, args) = parser.parse_args()
tb = top_block()
tb.Run(True)

Frequency sample rates are matched.
I cannot understand why changing the USRP sink interpolation affects
the FM demodulator.
They should be independent if the Ethernet traffic is under the limit.
I see a lot ot SSSSSS mesages and also audio underruns.

Many thanks for your help,
Jorge

Yes, I do not why it takes a lot of resources alhough I can see with gkrellm application that my CPUs are about 50-60%, so it is not so bad.

Try making the transition bandwidth on your filters a little wider (like
double their current width)–this will make the FIR filters shorter,
which
will reduce computational burden, although the existing filters aren’t
that long, it’s worth a shot.