From 6ac7576d32b8be601843c871327856ebd2b965d6 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Sun, 22 Jan 2012 17:44:04 -0500 Subject: sched: first attempt at working with aligned data sets. A block has an indicator on whether or not the buffers are aligned; they can use this to determine which Volk function to use or if to use Volk at all. --- gnuradio-core/src/lib/runtime/gr_block.cc | 30 ++++++++++++++++ gnuradio-core/src/lib/runtime/gr_block.h | 28 +++++++++++++++ gnuradio-core/src/lib/runtime/gr_block_executor.cc | 41 ++++++++++++++++++++-- 3 files changed, 96 insertions(+), 3 deletions(-) (limited to 'gnuradio-core/src/lib') diff --git a/gnuradio-core/src/lib/runtime/gr_block.cc b/gnuradio-core/src/lib/runtime/gr_block.cc index 9463869f5..78f77486b 100644 --- a/gnuradio-core/src/lib/runtime/gr_block.cc +++ b/gnuradio-core/src/lib/runtime/gr_block.cc @@ -34,6 +34,9 @@ gr_block::gr_block (const std::string &name, gr_io_signature_sptr output_signature) : gr_basic_block(name, input_signature, output_signature), d_output_multiple (1), + d_output_multiple_set(false), + d_unaligned(0), + d_is_unaligned(false), d_relative_rate (1.0), d_history(1), d_fixed_rate(false), @@ -75,9 +78,36 @@ gr_block::set_output_multiple (int multiple) if (multiple < 1) throw std::invalid_argument ("gr_block::set_output_multiple"); + d_output_multiple_set = true; d_output_multiple = multiple; } +void +gr_block::set_alignment (int multiple) +{ + if (multiple < 1) + throw std::invalid_argument ("gr_block::set_alignment_multiple"); + + d_output_multiple = multiple; +} + +void +gr_block::set_unaligned (int na) +{ + // unaligned value must be less than 0 and it doesn't make sense + // that it's larger than the alignment value. + if ((na < 0) || (na > d_output_multiple)) + throw std::invalid_argument ("gr_block::set_unaligned"); + + d_unaligned = na; +} + +void +gr_block::set_is_unaligned (bool u) +{ + d_is_unaligned = u; +} + void gr_block::set_relative_rate (double relative_rate) { diff --git a/gnuradio-core/src/lib/runtime/gr_block.h b/gnuradio-core/src/lib/runtime/gr_block.h index 86e0583e9..9171942e0 100644 --- a/gnuradio-core/src/lib/runtime/gr_block.h +++ b/gnuradio-core/src/lib/runtime/gr_block.h @@ -152,7 +152,32 @@ class GR_CORE_API gr_block : public gr_basic_block { */ void set_output_multiple (int multiple); int output_multiple () const { return d_output_multiple; } + bool output_multiple_set () const { return d_output_multiple_set; } + /*! + * \brief Constrains buffers to work on a set item alignment (for SIMD) + * + * set_alignment_multiple causes the scheduler to ensure that the noutput_items + * argument passed to forecast and general_work will be an integer multiple + * of \param multiple The default value is 1. + * + * This control is similar to the output_multiple setting, except + * that if the number of items passed to the block is less than the + * output_multiple, this value is ignored and the block can produce + * like normal. The d_unaligned value is set to the number of items + * the block is off by. In the next call to general_work, the + * noutput_items is set to d_unaligned or less until + * d_unaligned==0. The buffers are now aligned again and the aligned + * calls can be performed again. + */ + void set_alignment (int multiple); + int alignment () const { return d_output_multiple; } + + void set_unaligned (int na); + int unaligned () const { return d_unaligned; } + void set_is_unaligned (bool u); + bool is_unaligned () const { return d_is_unaligned; } + /*! * \brief Tell the scheduler \p how_many_items of input stream \p which_input were consumed. */ @@ -231,6 +256,9 @@ class GR_CORE_API gr_block : public gr_basic_block { private: int d_output_multiple; + bool d_output_multiple_set; + int d_unaligned; + bool d_is_unaligned; double d_relative_rate; // approx output_rate / input_rate gr_block_detail_sptr d_detail; // implementation details unsigned d_history; diff --git a/gnuradio-core/src/lib/runtime/gr_block_executor.cc b/gnuradio-core/src/lib/runtime/gr_block_executor.cc index ef53baf78..1c52c0e13 100644 --- a/gnuradio-core/src/lib/runtime/gr_block_executor.cc +++ b/gnuradio-core/src/lib/runtime/gr_block_executor.cc @@ -36,7 +36,7 @@ #include // must be defined to either 0 or 1 -#define ENABLE_LOGGING 0 +#define ENABLE_LOGGING 1 #if (ENABLE_LOGGING) #define LOG(x) do { x; } while(0) @@ -183,6 +183,7 @@ gr_block_executor::run_one_iteration() int noutput_items; int max_items_avail; int max_noutput_items = d_max_noutput_items; + int new_alignment; gr_block *m = d_block.get(); gr_block_detail *d = m->detail().get(); @@ -284,7 +285,7 @@ gr_block_executor::run_one_iteration() } // determine the minimum available output space - noutput_items = min_available_space (d, m->output_multiple ()); + noutput_items = min_available_space (d, m->output_multiple ()) - m->output_multiple(); if (ENABLE_LOGGING){ *d_log << " regular "; if (m->relative_rate() >= 1.0) @@ -307,7 +308,11 @@ gr_block_executor::run_one_iteration() // try to work it forward starting with max_items_avail. // We want to try to consume all the input we've got. int reqd_noutput_items = m->fixed_rate_ninput_to_noutput(max_items_avail); - reqd_noutput_items = round_up(reqd_noutput_items, m->output_multiple()); + + // only test this if we specifically set the output_multiple + if(m->output_multiple_set()) + reqd_noutput_items = round_up(reqd_noutput_items, m->output_multiple()); + if (reqd_noutput_items > 0 && reqd_noutput_items <= noutput_items) noutput_items = reqd_noutput_items; @@ -316,6 +321,30 @@ gr_block_executor::run_one_iteration() } noutput_items = std::min(noutput_items, max_noutput_items); + // Check if we're still unaligned; only use up items until we're + // aligned again. Otherwise, make sure we set the alignment + // requirement. + if(m->is_unaligned()) { + if(noutput_items >= m->unaligned()) { + noutput_items = round_up(noutput_items, m->alignment()) \ + - (m->alignment() - m->unaligned()); + new_alignment = 0; + } + else { + new_alignment = m->unaligned() - noutput_items; + } + } + else if(noutput_items < m->alignment()) { + //m->set_unaligned(m->alignment()); + new_alignment = m->alignment() - noutput_items; + m->set_unaligned(new_alignment); + m->set_is_unaligned(true); + } + else { + noutput_items = round_down(noutput_items, m->alignment()); + m->set_is_unaligned(false); + } + // ask the block how much input they need to produce noutput_items m->forecast (noutput_items, d_ninput_items_required); @@ -379,6 +408,12 @@ gr_block_executor::run_one_iteration() LOG(*d_log << " general_work: noutput_items = " << noutput_items << " result = " << n << std::endl); + // Adjust number of unaligned items left to process + if(m->is_unaligned()) { + m->set_unaligned(new_alignment); + m->set_is_unaligned(m->unaligned() != 0); + } + if(!propagate_tags(m->tag_propagation_policy(), d, d_start_nitems_read, m->relative_rate(), d_returned_tags)) -- cgit