diff options
author | Andy Walls <awalls.cx18@gmail.com> | 2017-12-11 19:25:01 -0500 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2018-02-03 14:23:32 +0100 |
commit | eee29fbe8ff4c58ae68af89384328f23f0a8e7b6 (patch) | |
tree | 35c9a212e0dfc2dbcf2cc3d01ef8e40bf22244c0 | |
parent | b0912d31f1a2cfea93a5588898cae0c652cd89d4 (diff) |
gnuradio-runtime: Optimize some buffer[_reader]_sptr grabs and releases
Optimize some reference counted buffer[_reader]_sptr grabs and releases
that show up as minor CPU wasters in profiling when there are a lot of
tags or some blocks that "return 0" often.
At high sample rates (e.g. 160 Msps), this can save ~2% CPU on
blocks that propagate a fair number of tags.
-rw-r--r-- | gnuradio-runtime/lib/block_detail.cc | 28 | ||||
-rw-r--r-- | gnuradio-runtime/lib/block_executor.cc | 55 | ||||
-rw-r--r-- | gnuradio-runtime/lib/single_threaded_scheduler.cc | 19 |
3 files changed, 66 insertions, 36 deletions
diff --git a/gnuradio-runtime/lib/block_detail.cc b/gnuradio-runtime/lib/block_detail.cc index 9e2e29fcd9..3da150ed8f 100644 --- a/gnuradio-runtime/lib/block_detail.cc +++ b/gnuradio-runtime/lib/block_detail.cc @@ -313,17 +313,19 @@ namespace gr { d_total_noutput_items = noutput_items; d_pc_start_time = (float)gr::high_res_timer_now(); for(size_t i=0; i < d_input.size(); i++) { - gr::thread::scoped_lock guard(*d_input[i]->mutex()); - float pfull = static_cast<float>(d_input[i]->items_available()) / - static_cast<float>(d_input[i]->max_possible_items_available()); + buffer_reader_sptr in_buf = d_input[i]; + gr::thread::scoped_lock guard(*in_buf->mutex()); + float pfull = static_cast<float>(in_buf->items_available()) / + static_cast<float>(in_buf->max_possible_items_available()); d_ins_input_buffers_full[i] = pfull; d_avg_input_buffers_full[i] = pfull; d_var_input_buffers_full[i] = 0; } for(size_t i=0; i < d_output.size(); i++) { - gr::thread::scoped_lock guard(*d_output[i]->mutex()); - float pfull = 1.0f - static_cast<float>(d_output[i]->space_available()) / - static_cast<float>(d_output[i]->bufsize()); + buffer_sptr out_buf = d_output[i]; + gr::thread::scoped_lock guard(*out_buf->mutex()); + float pfull = 1.0f - static_cast<float>(out_buf->space_available()) / + static_cast<float>(out_buf->bufsize()); d_ins_output_buffers_full[i] = pfull; d_avg_output_buffers_full[i] = pfull; d_var_output_buffers_full[i] = 0; @@ -351,9 +353,10 @@ namespace gr { d_avg_throughput = d_total_noutput_items / monitor_time; for(size_t i=0; i < d_input.size(); i++) { - gr::thread::scoped_lock guard(*d_input[i]->mutex()); - float pfull = static_cast<float>(d_input[i]->items_available()) / - static_cast<float>(d_input[i]->max_possible_items_available()); + buffer_reader_sptr in_buf = d_input[i]; + gr::thread::scoped_lock guard(*in_buf->mutex()); + float pfull = static_cast<float>(in_buf->items_available()) / + static_cast<float>(in_buf->max_possible_items_available()); d = pfull - d_avg_input_buffers_full[i]; d_ins_input_buffers_full[i] = pfull; @@ -362,9 +365,10 @@ namespace gr { } for(size_t i=0; i < d_output.size(); i++) { - gr::thread::scoped_lock guard(*d_output[i]->mutex()); - float pfull = 1.0f - static_cast<float>(d_output[i]->space_available()) / - static_cast<float>(d_output[i]->bufsize()); + buffer_sptr out_buf = d_output[i]; + gr::thread::scoped_lock guard(*out_buf->mutex()); + float pfull = 1.0f - static_cast<float>(out_buf->space_available()) / + static_cast<float>(out_buf->bufsize()); d = pfull - d_avg_output_buffers_full[i]; d_ins_output_buffers_full[i] = pfull; diff --git a/gnuradio-runtime/lib/block_executor.cc b/gnuradio-runtime/lib/block_executor.cc index 5c23df39a5..30bdacecf5 100644 --- a/gnuradio-runtime/lib/block_executor.cc +++ b/gnuradio-runtime/lib/block_executor.cc @@ -73,14 +73,15 @@ namespace gr { if(min_noutput_items == 0) min_noutput_items = 1; for(int i = 0; i < d->noutputs (); i++) { - gr::thread::scoped_lock guard(*d->output(i)->mutex()); - int avail_n = round_down(d->output(i)->space_available(), output_multiple); - int best_n = round_down(d->output(i)->bufsize()/2, output_multiple); + buffer_sptr out_buf = d->output(i); + gr::thread::scoped_lock guard(*out_buf->mutex()); + int avail_n = round_down(out_buf->space_available(), output_multiple); + int best_n = round_down(out_buf->bufsize()/2, output_multiple); if(best_n < min_noutput_items) throw std::runtime_error("Buffer too small for min_noutput_items"); int n = std::min(avail_n, best_n); if(n < min_noutput_items){ // We're blocked on output. - if(d->output(i)->done()){ // Downstream is done, therefore we're done. + if(out_buf->done()){ // Downstream is done, therefore we're done. return -1; } return 0; @@ -106,16 +107,28 @@ namespace gr { case block::TPP_CUSTOM: return true; case block::TPP_ALL_TO_ALL: + { // every tag on every input propogates to everyone downstream + std::vector<buffer_sptr> out_buf; + for(int i = 0; i < d->ninputs(); i++) { d->get_tags_in_range(rtags, i, start_nitems_read[i], d->nitems_read(i), block_id); + if (rtags.size() == 0) + continue; + + if (out_buf.size() == 0) { + out_buf.reserve(d->noutputs()); + for(int o = 0; o < d->noutputs(); o++) + out_buf.push_back(d->output(o)); + } + std::vector<tag_t>::iterator t; if(rrate == 1.0) { for(t = rtags.begin(); t != rtags.end(); t++) { for(int o = 0; o < d->noutputs(); o++) - d->output(o)->add_item_tag(*t); + out_buf[o]->add_item_tag(*t); } } else { @@ -123,25 +136,33 @@ namespace gr { tag_t new_tag = *t; new_tag.offset = ((double)new_tag.offset * rrate) + 0.5; for(int o = 0; o < d->noutputs(); o++) - d->output(o)->add_item_tag(new_tag); + out_buf[o]->add_item_tag(new_tag); } } } + } break; case block::TPP_ONE_TO_ONE: // tags from input i only go to output i // this requires d->ninputs() == d->noutputs; this is checked when this // type of tag-propagation system is selected in block_detail if(d->ninputs() == d->noutputs()) { + buffer_sptr out_buf; + for(int i = 0; i < d->ninputs(); i++) { d->get_tags_in_range(rtags, i, start_nitems_read[i], d->nitems_read(i), block_id); + if (rtags.size() == 0) + continue; + + out_buf = d->output(i); + std::vector<tag_t>::iterator t; for(t = rtags.begin(); t != rtags.end(); t++) { tag_t new_tag = *t; new_tag.offset = ((double)new_tag.offset * rrate) + 0.5; - d->output(i)->add_item_tag(new_tag); + out_buf->add_item_tag(new_tag); } } } @@ -149,7 +170,6 @@ namespace gr { std::cerr << "Error: block_executor: propagation_policy 'ONE-TO-ONE' requires ninputs == noutputs" << std::endl; return false; } - break; default: return true; @@ -244,9 +264,10 @@ namespace gr { /* * Acquire the mutex and grab local copies of items_available and done. */ - gr::thread::scoped_lock guard(*d->input(i)->mutex()); - d_ninput_items[i] = d->input(i)->items_available(); - d_input_done[i] = d->input(i)->done(); + buffer_reader_sptr in_buf = d->input(i); + gr::thread::scoped_lock guard(*in_buf->mutex()); + d_ninput_items[i] = in_buf->items_available(); + d_input_done[i] = in_buf->done(); } LOG(*d_log << " d_ninput_items[" << i << "] = " << d_ninput_items[i] << std::endl); @@ -288,9 +309,10 @@ namespace gr { /* * Acquire the mutex and grab local copies of items_available and done. */ - gr::thread::scoped_lock guard(*d->input(i)->mutex()); - d_ninput_items[i] = d->input(i)->items_available (); - d_input_done[i] = d->input(i)->done(); + buffer_reader_sptr in_buf = d->input(i); + gr::thread::scoped_lock guard(*in_buf->mutex()); + d_ninput_items[i] = in_buf->items_available (); + d_input_done[i] = in_buf->done(); } max_items_avail = std::max(max_items_avail, d_ninput_items[i]); } @@ -403,7 +425,8 @@ namespace gr { goto were_done; // Is it possible to ever fulfill this request? - if(d_ninput_items_required[i] > d->input(i)->max_possible_items_available()) { + buffer_reader_sptr in_buf = d->input(i); + if(d_ninput_items_required[i] > in_buf->max_possible_items_available()) { // Nope, never going to happen... std::cerr << "\nsched: <block " << m->name() << " (" << m->unique_id() << ")>" @@ -412,7 +435,7 @@ namespace gr { << " ninput_items_required = " << d_ninput_items_required[i] << "\n" << " max_possible_items_available = " - << d->input(i)->max_possible_items_available() << "\n" + << in_buf->max_possible_items_available() << "\n" << " If this is a filter, consider reducing the number of taps.\n"; goto were_done; } diff --git a/gnuradio-runtime/lib/single_threaded_scheduler.cc b/gnuradio-runtime/lib/single_threaded_scheduler.cc index c86d26ca3a..a85f390a30 100644 --- a/gnuradio-runtime/lib/single_threaded_scheduler.cc +++ b/gnuradio-runtime/lib/single_threaded_scheduler.cc @@ -112,9 +112,10 @@ namespace gr { int min_space = std::numeric_limits<int>::max(); for(int i = 0; i < d->noutputs (); i++) { - int n = round_down (d->output(i)->space_available (), output_multiple); + buffer_sptr out_buf = d->output(i); + int n = round_down (out_buf->space_available (), output_multiple); if(n == 0) { // We're blocked on output. - if(d->output(i)->done()) { // Downstream is done, therefore we're done. + if(out_buf->done()) { // Downstream is done, therefore we're done. return -1; } return 0; @@ -201,9 +202,10 @@ namespace gr { max_items_avail = 0; for(int i = 0; i < d->ninputs (); i++) { - ninput_items[i] = d->input(i)->items_available(); - //if (ninput_items[i] == 0 && d->input(i)->done()) - if(ninput_items[i] < m->output_multiple() && d->input(i)->done()) + buffer_reader_sptr in_buf = d->input(i); + ninput_items[i] = in_buf->items_available(); + //if (ninput_items[i] == 0 && in_buf->done()) + if(ninput_items[i] < m->output_multiple() && in_buf->done()) goto were_done; max_items_avail = std::max (max_items_avail, ninput_items[i]); @@ -294,12 +296,13 @@ namespace gr { } // We're blocked on input + buffer_reader_sptr in_buf = d->input(i); LOG(*d_log << " BLKD_IN\n"); - if(d->input(i)->done()) // If the upstream block is done, we're done + if(in_buf->done()) // If the upstream block is done, we're done goto were_done; // Is it possible to ever fulfill this request? - if(ninput_items_required[i] > d->input(i)->max_possible_items_available ()) { + if(ninput_items_required[i] > in_buf->max_possible_items_available ()) { // Nope, never going to happen... std::cerr << "\nsched: <block " << m->name() << " (" << m->unique_id() << ")>" @@ -308,7 +311,7 @@ namespace gr { << " ninput_items_required = " << ninput_items_required[i] << "\n" << " max_possible_items_available = " - << d->input(i)->max_possible_items_available() << "\n" + << in_buf->max_possible_items_available() << "\n" << " If this is a filter, consider reducing the number of taps.\n"; goto were_done; } |