summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Walls <awalls.cx18@gmail.com>2017-12-11 19:25:01 -0500
committerMartin Braun <martin.braun@ettus.com>2018-02-03 14:23:32 +0100
commiteee29fbe8ff4c58ae68af89384328f23f0a8e7b6 (patch)
tree35c9a212e0dfc2dbcf2cc3d01ef8e40bf22244c0
parentb0912d31f1a2cfea93a5588898cae0c652cd89d4 (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.cc28
-rw-r--r--gnuradio-runtime/lib/block_executor.cc55
-rw-r--r--gnuradio-runtime/lib/single_threaded_scheduler.cc19
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;
}