diff options
Diffstat (limited to 'host/utils/converter_benchmark.cpp')
-rw-r--r-- | host/utils/converter_benchmark.cpp | 278 |
1 files changed, 130 insertions, 148 deletions
diff --git a/host/utils/converter_benchmark.cpp b/host/utils/converter_benchmark.cpp index cb8cce519..07aec9170 100644 --- a/host/utils/converter_benchmark.cpp +++ b/host/utils/converter_benchmark.cpp @@ -5,32 +5,30 @@ // SPDX-License-Identifier: GPL-3.0-or-later // -#include <uhd/utils/safe_main.hpp> -#include <uhd/types/dict.hpp> #include <uhd/convert.hpp> #include <uhd/exception.hpp> -#include <boost/program_options.hpp> +#include <uhd/types/dict.hpp> +#include <uhd/utils/safe_main.hpp> +#include <stdint.h> +#include <boost/algorithm/string.hpp> #include <boost/format.hpp> -#include <boost/timer.hpp> #include <boost/lexical_cast.hpp> -#include <boost/algorithm/string.hpp> -#include <iostream> +#include <boost/program_options.hpp> +#include <boost/timer.hpp> +#include <complex> #include <iomanip> +#include <iostream> #include <map> -#include <complex> -#include <stdint.h> namespace po = boost::program_options; using namespace uhd::convert; -enum buf_init_t { - RANDOM, INC -}; +enum buf_init_t { RANDOM, INC }; // Convert `sc16_item32_le' -> `sc16' // Finds the first _ in format and returns the string // until then. Returns the entire string if no _ is found. -std::string format_to_type(const std::string &format) +std::string format_to_type(const std::string& format) { std::string ret_val = ""; for (size_t i = 0; i < format.length(); i++) { @@ -44,10 +42,8 @@ std::string format_to_type(const std::string &format) } void configure_conv( - converter::sptr conv, - const std::string &in_type, - const std::string &out_type -) { + converter::sptr conv, const std::string& in_type, const std::string& out_type) +{ if (in_type == "sc16") { if (out_type == "fc32") { std::cout << "Setting scalar to 32767." << std::endl; @@ -68,21 +64,19 @@ void configure_conv( } template <typename T> -void init_random_vector_complex_float(std::vector<char> &buf_ptr, const size_t n_items) +void init_random_vector_complex_float(std::vector<char>& buf_ptr, const size_t n_items) { - std::complex<T> * const buf = reinterpret_cast<std::complex<T> * const>(&buf_ptr[0]); + std::complex<T>* const buf = reinterpret_cast<std::complex<T>* const>(&buf_ptr[0]); for (size_t i = 0; i < n_items; i++) { buf[i] = std::complex<T>( - T(std::rand()/(RAND_MAX/2.0) - 1), - T(std::rand()/(RAND_MAX/2.0) - 1) - ); + T(std::rand() / (RAND_MAX / 2.0) - 1), T(std::rand() / (RAND_MAX / 2.0) - 1)); } } template <typename T> -void init_random_vector_complex_int(std::vector<char> &buf_ptr, const size_t n_items) +void init_random_vector_complex_int(std::vector<char>& buf_ptr, const size_t n_items) { - std::complex<T> * const buf = reinterpret_cast<std::complex<T> * const>(&buf_ptr[0]); + std::complex<T>* const buf = reinterpret_cast<std::complex<T>* const>(&buf_ptr[0]); for (size_t i = 0; i < n_items; i++) { buf[i] = std::complex<T>(T(std::rand()), T(std::rand())); } @@ -96,45 +90,45 @@ struct item32_sc12_3x }; template <typename T> -void init_random_vector_complex_sc12(std::vector<char> &buf_ptr, const size_t n_items) +void init_random_vector_complex_sc12(std::vector<char>& buf_ptr, const size_t n_items) { - item32_sc12_3x *const buf = reinterpret_cast<item32_sc12_3x * const>(&buf_ptr[0]); - if (n_items % 4) throw std::invalid_argument(""); + item32_sc12_3x* const buf = reinterpret_cast<item32_sc12_3x* const>(&buf_ptr[0]); + if (n_items % 4) + throw std::invalid_argument(""); for (size_t i = 0; i < n_items / 4; i++) { int16_t iq[8]; - for (auto &k : iq) k = rand() & 0xfff; - buf[i].line0 = iq[0] << 20 | iq[1] << 8 | iq[2] >> 4; + for (auto& k : iq) + k = rand() & 0xfff; + buf[i].line0 = iq[0] << 20 | iq[1] << 8 | iq[2] >> 4; buf[i].line1 = iq[2] << 28 | iq[3] << 16 | iq[4] << 4 | iq[5] >> 8; buf[i].line2 = iq[5] << 24 | iq[6] << 12 | iq[7] << 0; } } template <typename T> -void init_random_vector_real_int(std::vector<char> &buf_ptr, size_t n_items) +void init_random_vector_real_int(std::vector<char>& buf_ptr, size_t n_items) { - T * const buf = reinterpret_cast<T * const>(&buf_ptr[0]); + T* const buf = reinterpret_cast<T* const>(&buf_ptr[0]); for (size_t i = 0; i < n_items; i++) { buf[i] = T(std::rand()); } } // Fill a buffer with increasing numbers -template <typename T> -void init_inc_vector(std::vector<char> &buf_ptr, size_t n_items) +template <typename T> void init_inc_vector(std::vector<char>& buf_ptr, size_t n_items) { - T * const buf = reinterpret_cast<T * const>(&buf_ptr[0]); + T* const buf = reinterpret_cast<T* const>(&buf_ptr[0]); for (size_t i = 0; i < n_items; i++) { buf[i] = T(i); } } -void init_buffers( - std::vector< std::vector<char> > &buf, - const std::string &type, - size_t bytes_per_item, - buf_init_t buf_seed_mode -) { +void init_buffers(std::vector<std::vector<char>>& buf, + const std::string& type, + size_t bytes_per_item, + buf_init_t buf_seed_mode) +{ if (buf.empty()) { return; } @@ -144,26 +138,25 @@ void init_buffers( if (buf_seed_mode == INC) { for (size_t i = 0; i < buf.size(); i++) { if (type == "sc8") { - init_inc_vector< std::complex<int8_t> >(buf[i], n_items); + init_inc_vector<std::complex<int8_t>>(buf[i], n_items); } else if (type == "sc16") { - init_inc_vector< std::complex<int16_t> >(buf[i], n_items); + init_inc_vector<std::complex<int16_t>>(buf[i], n_items); } else if (type == "sc32") { - init_inc_vector< std::complex<int32_t> >(buf[i], n_items); + init_inc_vector<std::complex<int32_t>>(buf[i], n_items); } else if (type == "fc32") { - init_inc_vector< std::complex<float> >(buf[i], n_items); + init_inc_vector<std::complex<float>>(buf[i], n_items); } else if (type == "fc64") { - init_inc_vector< std::complex<double> >(buf[i], n_items); + init_inc_vector<std::complex<double>>(buf[i], n_items); } else if (type == "s8") { - init_inc_vector< int8_t >(buf[i], n_items); + init_inc_vector<int8_t>(buf[i], n_items); } else if (type == "s16") { - init_inc_vector< int16_t >(buf[i], n_items); + init_inc_vector<int16_t>(buf[i], n_items); } else if (type == "item32") { - init_inc_vector< uint32_t >(buf[i], n_items); + init_inc_vector<uint32_t>(buf[i], n_items); init_random_vector_real_int<uint32_t>(buf[i], n_items); } else { - throw uhd::runtime_error(str( - boost::format("Cannot handle data type: %s") % type - )); + throw uhd::runtime_error( + str(boost::format("Cannot handle data type: %s") % type)); } } @@ -193,21 +186,19 @@ void init_buffers( } else if (type == "item32") { init_random_vector_real_int<uint32_t>(buf[i], n_items); } else { - throw uhd::runtime_error(str( - boost::format("Cannot handle data type: %s") % type - )); + throw uhd::runtime_error( + str(boost::format("Cannot handle data type: %s") % type)); } } } // Returns time elapsed -double run_benchmark( - converter::sptr conv, - const std::vector<const void *> &input_buf_refs, - const std::vector<void *> &output_buf_refs, - size_t n_items, - size_t iterations -) { +double run_benchmark(converter::sptr conv, + const std::vector<const void*>& input_buf_refs, + const std::vector<void*>& output_buf_refs, + size_t n_items, + size_t iterations) +{ boost::timer benchmark_timer; for (size_t i = 0; i < iterations; i++) { conv->conv(input_buf_refs, output_buf_refs, n_items); @@ -215,71 +206,58 @@ double run_benchmark( return benchmark_timer.elapsed(); } -template <typename T> -std::string void_ptr_to_hexstring(const void *v_ptr, size_t index) +template <typename T> std::string void_ptr_to_hexstring(const void* v_ptr, size_t index) { - const T *ptr = reinterpret_cast<const T *>(v_ptr); + const T* ptr = reinterpret_cast<const T*>(v_ptr); return str(boost::format("%X") % ptr[index]); } -std::string item_to_hexstring( - const void *v_ptr, - size_t index, - const std::string &type -) { +std::string item_to_hexstring(const void* v_ptr, size_t index, const std::string& type) +{ if (type == "fc32") { return void_ptr_to_hexstring<uint64_t>(v_ptr, index); - } - else if (type == "sc16" || type == "item32") { + } else if (type == "sc16" || type == "item32") { return void_ptr_to_hexstring<uint32_t>(v_ptr, index); - } - else if (type == "sc8" || type == "s16") { + } else if (type == "sc8" || type == "s16") { return void_ptr_to_hexstring<uint16_t>(v_ptr, index); - } - else if (type == "u8") { + } else if (type == "u8") { return void_ptr_to_hexstring<uint8_t>(v_ptr, index); - } - else { + } else { return str(boost::format("<unhandled data type: %s>") % type); } } std::string item_to_string( - const void *v_ptr, - size_t index, - const std::string &type, - const bool print_hex -) { + const void* v_ptr, size_t index, const std::string& type, const bool print_hex) +{ if (print_hex) { return item_to_hexstring(v_ptr, index, type); } if (type == "sc16") { - const std::complex<int16_t> *ptr = reinterpret_cast<const std::complex<int16_t> *>(v_ptr); + const std::complex<int16_t>* ptr = + reinterpret_cast<const std::complex<int16_t>*>(v_ptr); return boost::lexical_cast<std::string>(ptr[index]); - } - else if (type == "sc8") { - const std::complex<int8_t> *ptr = reinterpret_cast<const std::complex<int8_t> *>(v_ptr); + } else if (type == "sc8") { + const std::complex<int8_t>* ptr = + reinterpret_cast<const std::complex<int8_t>*>(v_ptr); return boost::lexical_cast<std::string>(ptr[index]); - } - else if (type == "fc32") { - const std::complex<float> *ptr = reinterpret_cast<const std::complex<float> *>(v_ptr); + } else if (type == "fc32") { + const std::complex<float>* ptr = + reinterpret_cast<const std::complex<float>*>(v_ptr); return boost::lexical_cast<std::string>(ptr[index]); - } - else if (type == "item32") { - const uint32_t *ptr = reinterpret_cast<const uint32_t *>(v_ptr); + } else if (type == "item32") { + const uint32_t* ptr = reinterpret_cast<const uint32_t*>(v_ptr); return boost::lexical_cast<std::string>(ptr[index]); - } - else if (type == "s16") { - const int16_t *ptr = reinterpret_cast<const int16_t *>(v_ptr); + } else if (type == "s16") { + const int16_t* ptr = reinterpret_cast<const int16_t*>(v_ptr); return boost::lexical_cast<std::string>(ptr[index]); - } - else { + } else { return str(boost::format("<unhandled data type: %s>") % type); } } -int UHD_SAFE_MAIN(int argc, char *argv[]) +int UHD_SAFE_MAIN(int argc, char* argv[]) { std::string in_format, out_format; std::string priorities; @@ -311,15 +289,19 @@ int UHD_SAFE_MAIN(int argc, char *argv[]) po::store(po::parse_command_line(argc, argv, desc), vm); po::notify(vm); - //print the help message - if (vm.count("help")){ - std::cout << boost::format("UHD Converter Benchmark Tool %s") % desc << std::endl << std::endl; - std::cout << " Use this to benchmark or debug converters." << std::endl - << " When using as a benchmark tool, it will output the execution time\n" - " for every conversion run in CSV format to stdout. Every line between\n" - " the output delimiters {{{ }}} is of the format: <PRIO>,<TIME IN MILLISECONDS>\n" - " When using for converter debugging, every line is formatted as\n" - " <INPUT_VALUE>,<OUTPUT_VALUE>\n" << std::endl; + // print the help message + if (vm.count("help")) { + std::cout << boost::format("UHD Converter Benchmark Tool %s") % desc << std::endl + << std::endl; + std::cout + << " Use this to benchmark or debug converters." << std::endl + << " When using as a benchmark tool, it will output the execution time\n" + " for every conversion run in CSV format to stdout. Every line between\n" + " the output delimiters {{{ }}} is of the format: <PRIO>,<TIME IN " + "MILLISECONDS>\n" + " When using for converter debugging, every line is formatted as\n" + " <INPUT_VALUE>,<OUTPUT_VALUE>\n" + << std::endl; return EXIT_FAILURE; } @@ -329,7 +311,9 @@ int UHD_SAFE_MAIN(int argc, char *argv[]) } else if (seed_mode == "random") { buf_seed_mode = RANDOM; } else { - std::cout << "Invalid argument: --seed-mode must be either 'incremental' or 'random'." << std::endl; + std::cout + << "Invalid argument: --seed-mode must be either 'incremental' or 'random'." + << std::endl; } bool debug_mode = vm.count("debug-converter") > 0; @@ -343,13 +327,13 @@ int UHD_SAFE_MAIN(int argc, char *argv[]) converter_id.output_format = out_format; converter_id.num_inputs = n_inputs; converter_id.num_outputs = n_outputs; - std::cout << "Requested converter format: " << converter_id.to_string() - << std::endl; + std::cout << "Requested converter format: " << converter_id.to_string() << std::endl; uhd::dict<priority_type, converter::sptr> conv_list; if (priorities == "default" or priorities.empty()) { try { - conv_list[prio] = get_converter(converter_id, prio)(); // Can throw a uhd::key_error - } catch(const uhd::key_error &) { + conv_list[prio] = + get_converter(converter_id, prio)(); // Can throw a uhd::key_error + } catch (const uhd::key_error&) { std::cout << "No converters found." << std::endl; return EXIT_FAILURE; } @@ -357,7 +341,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]) for (priority_type i = 0; i < max_prio; i++) { try { // get_converter() returns a factory function, execute that immediately: - converter::sptr conv_for_prio = get_converter(converter_id, i)(); // Can throw a uhd::key_error + converter::sptr conv_for_prio = + get_converter(converter_id, i)(); // Can throw a uhd::key_error conv_list[i] = conv_for_prio; } catch (...) { continue; @@ -365,15 +350,15 @@ int UHD_SAFE_MAIN(int argc, char *argv[]) } } else { // Assume that priorities contains a list of prios (e.g. 0,2,3) std::vector<std::string> prios_in_list; - boost::split( - prios_in_list, - priorities, - boost::is_any_of(","), // Split at , - boost::token_compress_on // Avoid empty results + boost::split(prios_in_list, + priorities, + boost::is_any_of(","), // Split at , + boost::token_compress_on // Avoid empty results ); - for(const std::string &this_prio: prios_in_list) { + for (const std::string& this_prio : prios_in_list) { size_t prio_index = boost::lexical_cast<size_t>(this_prio); - converter::sptr conv_for_prio = get_converter(converter_id, prio_index)(); // Can throw a uhd::key_error + converter::sptr conv_for_prio = + get_converter(converter_id, prio_index)(); // Can throw a uhd::key_error conv_list[prio_index] = conv_for_prio; } } @@ -383,25 +368,27 @@ int UHD_SAFE_MAIN(int argc, char *argv[]) // First, convert the types to plain types (e.g. sc16_item32_le -> sc16) const std::string in_type = format_to_type(in_format); const std::string out_type = format_to_type(out_format); - const size_t in_size = get_bytes_per_item(in_type); - const size_t out_size = get_bytes_per_item(out_type); + const size_t in_size = get_bytes_per_item(in_type); + const size_t out_size = get_bytes_per_item(out_type); // Create the buffers and fill them with random data & zeros, respectively - std::vector< std::vector<char> > input_buffers(n_inputs, std::vector<char>(in_size * n_samples, 0)); - std::vector< std::vector<char> > output_buffers(n_outputs, std::vector<char>(out_size * n_samples, 0)); + std::vector<std::vector<char>> input_buffers( + n_inputs, std::vector<char>(in_size * n_samples, 0)); + std::vector<std::vector<char>> output_buffers( + n_outputs, std::vector<char>(out_size * n_samples, 0)); init_buffers(input_buffers, in_type, in_size, buf_seed_mode); // Create ref vectors for the converter: - std::vector<const void *> input_buf_refs(n_inputs); - std::vector<void *> output_buf_refs(n_outputs); + std::vector<const void*> input_buf_refs(n_inputs); + std::vector<void*> output_buf_refs(n_outputs); for (size_t i = 0; i < n_inputs; i++) { - input_buf_refs[i] = reinterpret_cast<const void *>(&input_buffers[i][0]); + input_buf_refs[i] = reinterpret_cast<const void*>(&input_buffers[i][0]); } for (size_t i = 0; i < n_outputs; i++) { - output_buf_refs[i] = reinterpret_cast<void *>(&output_buffers[i][0]); + output_buf_refs[i] = reinterpret_cast<void*>(&output_buffers[i][0]); } /// Final configurations to the converter: std::cout << "Configuring converters:" << std::endl; - for(priority_type prio_i: conv_list.keys()) { + for (priority_type prio_i : conv_list.keys()) { std::cout << "* [" << prio_i << "]: "; configure_conv(conv_list[prio_i], in_type, out_type); } @@ -410,38 +397,33 @@ int UHD_SAFE_MAIN(int argc, char *argv[]) std::cout << "{{{" << std::endl; if (not debug_mode) { std::cout << "prio,duration_ms,avg_duration_ms,n_samples,iterations" << std::endl; - for(priority_type prio_i: conv_list.keys()) { - double duration = run_benchmark( - conv_list[prio_i], - input_buf_refs, - output_buf_refs, - n_samples, - iterations - ); - std::cout << boost::format("%i,%d,%d,%d,%d") - % prio_i - % (duration * 1000) - % (duration * 1000.0 / iterations) - % n_samples - % iterations - << std::endl; + for (priority_type prio_i : conv_list.keys()) { + double duration = run_benchmark(conv_list[prio_i], + input_buf_refs, + output_buf_refs, + n_samples, + iterations); + std::cout << boost::format("%i,%d,%d,%d,%d") % prio_i % (duration * 1000) + % (duration * 1000.0 / iterations) % n_samples % iterations + << std::endl; } } /// Or run debug mode, which runs one conversion and prints the results //// if (debug_mode) { // Only run on the first converter: - run_benchmark( - conv_list[conv_list.keys().at(0)], + run_benchmark(conv_list[conv_list.keys().at(0)], input_buf_refs, output_buf_refs, n_samples, - iterations - ); + iterations); for (size_t i = 0; i < n_samples; i++) { std::cout << item_to_string(input_buf_refs[0], i, in_type, vm.count("hex")) << ";" - << item_to_string(reinterpret_cast< const void * >(output_buf_refs[0]), i, out_type, vm.count("hex")) + << item_to_string(reinterpret_cast<const void*>(output_buf_refs[0]), + i, + out_type, + vm.count("hex")) << std::endl; } } |