Skip to content

Commit

Permalink
[FEATURE] Improved timing output
Browse files Browse the repository at this point in the history
  • Loading branch information
eseiler committed Oct 25, 2023
1 parent 0b115fa commit c12d1b8
Show file tree
Hide file tree
Showing 19 changed files with 517 additions and 206 deletions.
29 changes: 4 additions & 25 deletions include/raptor/argument_parsing/build_arguments.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@

#include <seqan3/search/kmer_index/shape.hpp>

#include <raptor/argument_parsing/memory_usage.hpp>
#include <raptor/strong_types.hpp>

#include <hibf/misc/timer.hpp>

namespace raptor
Expand All @@ -34,7 +31,7 @@ struct build_arguments
seqan3::shape shape{seqan3::ungapped{kmer_size}};

// Related to IBF
std::filesystem::path out_path{"./"};
std::filesystem::path out_path{};
uint64_t bins{64};
mutable uint64_t bits{4096}; // Allow to change bits for each partition
uint64_t hash{2};
Expand All @@ -48,6 +45,7 @@ struct build_arguments
bool is_hibf{false};
bool input_is_minimiser{false};
bool quiet{false};
std::filesystem::path timing_out{};

// Timers do not copy the stored duration upon copy construction/assignment
mutable seqan::hibf::concurrent_timer wall_clock_timer{};
Expand All @@ -58,27 +56,8 @@ struct build_arguments
mutable seqan::hibf::concurrent_timer fill_ibf_timer{};
mutable seqan::hibf::concurrent_timer store_index_timer{};

void print_timings() const
{
if (quiet)
return;
std::cerr << std::fixed << std::setprecision(2) << "============= Timings =============\n";
std::cerr << "Wall clock time [s]: " << wall_clock_timer.in_seconds() << '\n';
std::cerr << "Peak memory usage " << formatted_peak_ram() << '\n';
if (!is_hibf)
std::cerr << "Determine IBF size [s]: " << bin_size_timer.in_seconds() << '\n';
std::cerr << "Index allocation [s]: " << index_allocation_timer.in_seconds() << '\n';
std::cerr << "User bin I/O avg per thread [s]: " << user_bin_io_timer.in_seconds() / threads << '\n';
std::cerr << "User bin I/O sum [s]: " << user_bin_io_timer.in_seconds() << '\n';
if (is_hibf)
{
std::cerr << "Merge kmer sets avg per thread [s]: " << merge_kmers_timer.in_seconds() / threads << '\n';
std::cerr << "Merge kmer sets sum [s]: " << merge_kmers_timer.in_seconds() << '\n';
}
std::cerr << "Fill IBF avg per thread [s]: " << fill_ibf_timer.in_seconds() / threads << '\n';
std::cerr << "Fill IBF sum [s]: " << fill_ibf_timer.in_seconds() << '\n';
std::cerr << "Store index [s]: " << store_index_timer.in_seconds() << '\n';
}
void print_timings() const;
void write_timings_to_file() const;
};

} // namespace raptor
94 changes: 94 additions & 0 deletions include/raptor/argument_parsing/formatted_bytes.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// --------------------------------------------------------------------------------------------------
// Copyright (c) 2006-2023, Knut Reinert & Freie Universität Berlin
// Copyright (c) 2016-2023, Knut Reinert & MPI für molekulare Genetik
// This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
// shipped with this file and also available at: https://github.com/seqan/raptor/blob/main/LICENSE.md
// --------------------------------------------------------------------------------------------------

/*!\file
* \brief Provides raptor::formatted_bytes.
* \author Enrico Seiler <enrico.seiler AT fu-berlin.de>
*/

#pragma once

#include <cassert>
#include <cstddef>
#include <cstdint>
#include <string>

namespace raptor
{

[[nodiscard]] inline std::string formatted_bytes(size_t const bytes)
{
assert(bytes > 0);

size_t iterations{};
size_t integer{bytes};

while (integer >> 10u && iterations < 6u)
{
integer >>= 10u;
++iterations;
}

// While this is a bit more involved, we can avoid using floating point numbers.
auto first_decimal_position = [&]()
{
assert(iterations > 0u);
size_t decimal{bytes};
decimal -= integer << (iterations * 10u); // Substract bytes represented by integer, e.g. -5GiB
decimal >>= (iterations - 1u) * 10u; // Shift to next smallest unit, e.g. 800MiB
decimal = decimal * 1000u / 1024u; // Account for using decimal system, i.e. 800MiB != 0.8GiB
size_t const diff{decimal - (decimal / 100u) * 100u}; // We want to round up to 1 decimal position
uint32_t const round_up{diff >= 50u};
decimal += round_up * 100u - diff;
decimal /= 100u;
return decimal;
};

auto formatted_string = [&]()
{
static constexpr int8_t int_to_char_offset{'0'}; // int 0 as char: char{0 + 48} = '0'
size_t const decimal = iterations ? first_decimal_position() : 0u;
assert(decimal <= 10u);

if (!iterations) // No decimals for Bytes
return std::to_string(integer);
else if (decimal < 10u) // No need to round integer part
return std::to_string(integer) + '.' + static_cast<char>(decimal + int_to_char_offset);
else // Round integer part, e.g., 5.99 MiB should report 6.0 MiB
{
++integer;
// Check whether rounding results in a change of unit, e.g. 1023.99MiB to 1.0GiB
if (integer >> 10u)
{
++iterations;
integer >>= 10u;
}
return std::to_string(integer) + ".0";
}
};

std::string const formatted{formatted_string()};
switch (iterations)
{
case 0:
return "[Bytes]: " + formatted;
case 1:
return "[KiB]: " + formatted;
case 2:
return "[MiB]: " + formatted;
case 3:
return "[GiB]: " + formatted;
case 4:
return "[TiB]: " + formatted;
case 5:
return "[PiB]: " + formatted;
default:
return "[EiB]: " + formatted;
}
}

} // namespace raptor
48 changes: 48 additions & 0 deletions include/raptor/argument_parsing/formatted_index_size.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// --------------------------------------------------------------------------------------------------
// Copyright (c) 2006-2023, Knut Reinert & Freie Universität Berlin
// Copyright (c) 2016-2023, Knut Reinert & MPI für molekulare Genetik
// This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
// shipped with this file and also available at: https://github.com/seqan/raptor/blob/main/LICENSE.md
// --------------------------------------------------------------------------------------------------

/*!\file
* \brief Provides raptor::formatted_index_size.
* \author Enrico Seiler <enrico.seiler AT fu-berlin.de>
*/

#pragma once

#include <cassert>
#include <cstddef>
#include <filesystem>
#include <string>

#include <raptor/argument_parsing/formatted_bytes.hpp>

namespace raptor
{

[[nodiscard]] inline size_t index_size_in_KiB(std::filesystem::path index_path, uint8_t const parts)
{
size_t index_size_in_bytes{};
if (parts == 1u)
{
index_size_in_bytes = std::filesystem::file_size(index_path);
}
else
{
for (size_t part = 0u; part < parts; ++part)
{
index_size_in_bytes += std::filesystem::file_size(index_path.string() + "_" + std::to_string(part));
}
}

return index_size_in_bytes >> 10;
}

[[nodiscard]] inline std::string formatted_index_size(std::filesystem::path index_path, uint8_t const parts)
{
return formatted_bytes(index_size_in_KiB(index_path, parts) << 10);
}

} // namespace raptor
91 changes: 9 additions & 82 deletions include/raptor/argument_parsing/memory_usage.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,25 @@
#include <cstdint>
#include <string>

#include <raptor/argument_parsing/formatted_bytes.hpp>

#if __has_include(<sys/resource.h>)
# include <sys/resource.h>
#endif

namespace raptor
{

namespace detail
{

#if __has_include(<sys/resource.h>)
// Returns -1 if not available. Actually returns bytes instead of KiB on macOS.
inline long peak_ram_in_KiB()
{
rusage usage;
# if __APPLE__
return getrusage(RUSAGE_SELF, &usage) == 0 ? (usage.ru_maxrss >> 10) : -1L;
# else
return getrusage(RUSAGE_SELF, &usage) == 0 ? usage.ru_maxrss : -1L;
# endif
}
#else
inline long peak_ram_in_KiB()
Expand All @@ -40,89 +43,13 @@ inline long peak_ram_in_KiB()
}
#endif

[[nodiscard]] inline std::string formatted_peak_ram(size_t const bytes)
{
assert(bytes > 0);

size_t iterations{};
size_t integer{bytes};

while (integer >> 10u && iterations < 6u)
{
integer >>= 10u;
++iterations;
}

// While this is a bit more involved, we can avoid using floating point numbers.
auto first_decimal_position = [&]()
{
assert(iterations > 0u);
size_t decimal{bytes};
decimal -= integer << (iterations * 10u); // Substract bytes represented by integer, e.g. -5GiB
decimal >>= (iterations - 1u) * 10u; // Shift to next smallest unit, e.g. 800MiB
decimal = decimal * 1000u / 1024u; // Account for using decimal system, i.e. 800MiB != 0.8GiB
size_t const diff{decimal - (decimal / 100u) * 100u}; // We want to round up to 1 decimal position
uint32_t const round_up{diff >= 50u};
decimal += round_up * 100u - diff;
decimal /= 100u;
return decimal;
};

auto formatted_string = [&]()
{
static constexpr int8_t int_to_char_offset{'0'}; // int 0 as char: char{0 + 48} = '0'
size_t const decimal = iterations ? first_decimal_position() : 0u;
assert(decimal <= 10u);

if (!iterations) // No decimals for Bytes
return std::to_string(integer);
else if (decimal < 10u) // No need to round integer part
return std::to_string(integer) + '.' + static_cast<char>(decimal + int_to_char_offset);
else // Round integer part, e.g., 5.99 MiB should report 6.0 MiB
{
++integer;
// Check whether rounding results in a change of unit, e.g. 1023.99MiB to 1.0GiB
if (integer >> 10u)
{
++iterations;
integer >>= 10u;
}
return std::to_string(integer) + ".0";
}
};

std::string const formatted{formatted_string()};
switch (iterations)
{
case 0:
return "[Bytes]: " + formatted;
case 1:
return "[KiB]: " + formatted;
case 2:
return "[MiB]: " + formatted;
case 3:
return "[GiB]: " + formatted;
case 4:
return "[TiB]: " + formatted;
case 5:
return "[PiB]: " + formatted;
default:
return "[EiB]: " + formatted;
}
}

} // namespace detail

[[nodiscard]] inline std::string formatted_peak_ram()
{
long const peak_ram_KiB = detail::peak_ram_in_KiB();
long const peak_ram_KiB = peak_ram_in_KiB();
if (peak_ram_KiB == -1L)
return {": Not available"}; // GCOVR_EXCL_LINE
#if __APPLE__
return detail::formatted_peak_ram(static_cast<size_t>(peak_ram_KiB));
#else
return detail::formatted_peak_ram(static_cast<size_t>(peak_ram_KiB) << 10);
#endif

return formatted_bytes(static_cast<size_t>(peak_ram_KiB) << 10);
}

} // namespace raptor
18 changes: 4 additions & 14 deletions include/raptor/argument_parsing/search_arguments.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include <seqan3/search/kmer_index/shape.hpp>

#include <raptor/argument_parsing/formatted_index_size.hpp>
#include <raptor/argument_parsing/memory_usage.hpp>
#include <raptor/threshold/threshold_parameters.hpp>

Expand Down Expand Up @@ -54,6 +55,7 @@ struct search_arguments
bool is_hibf{false};
bool cache_thresholds{false};
bool quiet{false};
std::filesystem::path timing_out{};

// Timers do not copy the stored duration upon copy construction/assignment
mutable seqan::hibf::concurrent_timer wall_clock_timer{};
Expand All @@ -64,20 +66,8 @@ struct search_arguments
mutable seqan::hibf::concurrent_timer query_ibf_timer{};
mutable seqan::hibf::concurrent_timer generate_results_timer{};

void print_timings() const
{
if (quiet)
return;
std::cerr << std::fixed << std::setprecision(2) << "============= Timings =============\n";
std::cerr << "Wall clock time [s]: " << wall_clock_timer.in_seconds() << '\n';
std::cerr << "Peak memory usage " << formatted_peak_ram() << '\n';
std::cerr << "Determine query length [s]: " << query_length_timer.in_seconds() << '\n';
std::cerr << "Query file I/O [s]: " << query_file_io_timer.in_seconds() << '\n';
std::cerr << "Load index [s]: " << load_index_timer.in_seconds() << '\n';
std::cerr << "Compute minimiser [s]: " << compute_minimiser_timer.in_seconds() / threads << '\n';
std::cerr << "Query IBF [s]: " << query_ibf_timer.in_seconds() / threads << '\n';
std::cerr << "Generate results [s]: " << generate_results_timer.in_seconds() / threads << '\n';
}
void print_timings() const;
void write_timings_to_file() const;

raptor::threshold::threshold_parameters make_threshold_parameters() const noexcept
{
Expand Down
2 changes: 2 additions & 0 deletions src/argument_parsing/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,13 @@ if (NOT TARGET raptor_argument_parsing)
endif ()

add_library ("raptor_argument_parsing" STATIC
build_arguments.cpp
build_parsing.cpp
compute_bin_size.cpp
init_shared_meta.cpp
parse_bin_path.cpp
prepare_parsing.cpp
search_arguments.cpp
search_parsing.cpp
upgrade_parsing.cpp
)
Expand Down
Loading

0 comments on commit c12d1b8

Please sign in to comment.