transport: Removing recv() task barrier for conversion calls

This modifies super_recv_packet_handler to replace threads & task
barriers in the conversion call with serializing the conversion calls.
Experiments have shown that for most cases, this is superior in
performance than spawning threads and waiting for them to synchronize.
This commit is contained in:
Paul David 2016-05-11 13:12:17 -07:00 committed by Martin Braun
parent e8202128c9
commit 9ebbb8eb6c

View File

@ -24,7 +24,6 @@
#include <uhd/stream.hpp>
#include <uhd/utils/msg.hpp>
#include <uhd/utils/tasks.hpp>
#include <uhd/utils/atomic.hpp>
#include <uhd/utils/byteswap.hpp>
#include <uhd/types/metadata.hpp>
#include <uhd/transport/vrt_if_packet.hpp>
@ -35,7 +34,6 @@
#include <boost/format.hpp>
#include <boost/bind.hpp>
#include <boost/make_shared.hpp>
#include <boost/thread/barrier.hpp>
#include <iostream>
#include <vector>
@ -92,22 +90,15 @@ public:
}
~recv_packet_handler(void){
_task_barrier.interrupt();
_task_handlers.clear();
/* NOP */
}
//! Resize the number of transport channels
void resize(const size_t size){
if (this->size() == size) return;
_task_handlers.clear();
_props.resize(size);
//re-initialize all buffers infos by re-creating the vector
_buffers_infos = std::vector<buffers_info_type>(4, buffers_info_type(size));
_task_barrier.resize(size);
_task_handlers.resize(size);
for (size_t i = 1/*skip 0*/; i < size; i++){
_task_handlers[i] = task::make(boost::bind(&recv_packet_handler::converter_thread_task, this, i));
};
}
//! Get the channel width of this handler
@ -668,7 +659,9 @@ private:
_convert_bytes_to_copy = bytes_to_copy;
//perform N channels of conversion
converter_thread_task(0);
for (size_t i = 0; i < buffs.size(); i++) {
convert_to_out_buff(i);
}
//update the copy buffer's availability
info.data_bytes_to_copy -= bytes_to_copy;
@ -681,15 +674,15 @@ private:
return nsamps_to_copy_per_io_buff;
}
/*******************************************************************
* Perform one thread's work of the conversion task.
* The entry and exit use a dual synchronization barrier,
* to wait for data to become ready and block until completion.
******************************************************************/
UHD_INLINE void converter_thread_task(const size_t index)
/*! Run the conversion from the internal buffers to the user's output
* buffer.
*
* - Calls the converter
* - Releases internal data buffers
* - Updates read/write pointers
*/
inline void convert_to_out_buff(const size_t index)
{
_task_barrier.wait();
//shortcut references to local data structures
buffers_info_type &buff_info = get_curr_buffer_info();
per_buffer_info_type &info = buff_info[index];
@ -713,13 +706,9 @@ private:
if (buff_info.data_bytes_to_copy == _convert_bytes_to_copy){
info.buff.reset(); //effectively a release
}
if (index == 0) _task_barrier.wait_others();
}
//! Shared variables for the worker threads
reusable_barrier _task_barrier;
std::vector<task::sptr> _task_handlers;
size_t _convert_nsamps;
const rx_streamer::buffs_type *_convert_buffs;
size_t _convert_buffer_offset_bytes;