cuDDL
Loading...
Searching...
No Matches
Classes | Public Member Functions | List of all members
cuddl::detail::fastx_load_pool Class Reference

#include <fastx_sequence_file.hpp>

Public Member Functions

 fastx_load_pool (std::span< std::filesystem::path const > paths, size_t workers, decompression_source source={}, size_t window=0, bool defer_fasta=false, bool completion_order=false, uint32_t pack_k=0)
 
 ~fastx_load_pool ()
 
 fastx_load_pool (fastx_load_pool const &)=delete
 
fastx_load_pool & operator= (fastx_load_pool const &)=delete
 
Result< std::unique_ptr< fastx_sequence_file > > take (size_t id)
 
Result< std::pair< size_t, std::unique_ptr< fastx_sequence_file > > > take_ready ()
 
Result< std::optional< std::pair< size_t, std::unique_ptr< fastx_sequence_file > > > > take_ready_until_limit ()
 take_ready, or nothing once every id below the cap limit is taken.
 
size_t ready ()
 Completion-order results waiting to be taken.
 
size_t cap (size_t limit)
 Stops the loaders before id limit, or after the ids they already claimed.
 

Detailed Description

Definition at line 1796 of file fastx_sequence_file.hpp.

Constructor & Destructor Documentation

◆ fastx_load_pool() [1/2]

cuddl::detail::fastx_load_pool::fastx_load_pool ( std::span< std::filesystem::path const >  paths,
size_t  workers,
decompression_source  source = {},
size_t  window = 0,
bool  defer_fasta = false,
bool  completion_order = false,
uint32_t  pack_k = 0 
)
inline
Parameters
pathsFiles the pool loads in order.
workersLoader threads.
sourceDecompression buffer source; the default detects gzip by magic bytes.
windowFiles the loaders may hold ahead of the consumer, at least one per worker. With ordered collection, the window hides a slow file: with a window of one worker-worth there is no slack, and the consumer waits on the straggler while the other loaders sit idle.
defer_fastaLeave eligible FASTA bytes for a GPU normaliser.
completion_orderCollect through take_ready instead of take(id).
pack_kNonzero packs each loaded file into two-bit runs for k-mers this long.

Definition at line 1808 of file fastx_sequence_file.hpp.

1811 {},
1812 size_t window = 0,
1813 bool defer_fasta = false,
1814 bool completion_order = false,
1815 uint32_t pack_k = 0
1816 )
1817 : paths_(paths),
1818 workers_(std::max(size_t{1}, workers)),
1819 window_(std::max({size_t{1}, window, workers_})),
1820 source_(source),
1821 defer_fasta_(defer_fasta),
1822 pack_k_(pack_k),
1823 results_(paths.size()),
1824 errors_(paths.size()),
1825 ready_(completion_order ? window_ : 0),
1826 retired_(defer_fasta ? window_ : 0) {
1827 threads_.reserve(workers_);
1828 if (defer_fasta_) retirer_ = std::thread([this] { retire_files(); });
1829 // A reader spends most of its time waiting on storage, so there are as many as the reads
1830 // a parallel file system needs in flight, however few the loaders.
1831 auto const readers =
1832 ablated("read-depth") ? workers_
1833 : std::min(window_, std::max(workers_, parallel_read_depth));
1834 readers_.reserve(readers);
1835 for (size_t i = 0; i < readers; ++i) {
1836 readers_.emplace_back([this] { read_files(); });
1837 }
1838 for (size_t i = 0; i < workers_; ++i) threads_.emplace_back([this] { work(); });
1839 }
constexpr size_t parallel_read_depth
Reads a parallel file system needs in flight to give one node its bandwidth: on MOGON's Lustre,...
constexpr bool ablated(std::string_view) noexcept
Always false: this build compiles the ablation switches out.
Definition ablation.hpp:82

◆ ~fastx_load_pool()

cuddl::detail::fastx_load_pool::~fastx_load_pool ( )
inline

Definition at line 1840 of file fastx_sequence_file.hpp.

1840 {
1841 {
1842 std::lock_guard lock(mutex_);
1843 stop_ = true;
1844 }
1845 assign_.notify_all();
1846 mapped_ready_.notify_all();
1847 for (auto& thread : readers_) thread.join();
1848 for (auto& thread : threads_) thread.join();
1849 // Loaders may be waiting for retirement space, so stop the reaper only after joining them.
1850 if (retirer_.joinable()) {
1851 {
1852 std::lock_guard lock(retired_mutex_);
1853 retire_stop_ = true;
1854 }
1855 retired_ready_.notify_one();
1856 retirer_.join();
1857 }
1858 }

◆ fastx_load_pool() [2/2]

cuddl::detail::fastx_load_pool::fastx_load_pool ( fastx_load_pool const &  )
delete

Member Function Documentation

◆ cap()

size_t cuddl::detail::fastx_load_pool::cap ( size_t  limit)
inline

Stops the loaders before id limit, or after the ids they already claimed.

A second consumer can own the ids past the returned limit without racing the loaders.

Returns
How many ids the pool loads in total.

Definition at line 1910 of file fastx_sequence_file.hpp.

1910 {
1911 {
1912 std::lock_guard lock(mutex_);
1913 limit_ = std::clamp(limit, claimed_end_, limit_);
1914 limit = limit_;
1915 }
1916 assign_.notify_all();
1917 filled_.notify_all();
1918 mapped_ready_.notify_all();
1919 return limit;
1920 }

◆ operator=()

fastx_load_pool & cuddl::detail::fastx_load_pool::operator= ( fastx_load_pool const &  )
delete

◆ ready()

size_t cuddl::detail::fastx_load_pool::ready ( )
inline

Completion-order results waiting to be taken.

Definition at line 1901 of file fastx_sequence_file.hpp.

1901 {
1902 std::lock_guard lock(mutex_);
1903 return ready_count_;
1904 }

◆ take()

Result< std::unique_ptr< fastx_sequence_file > > cuddl::detail::fastx_load_pool::take ( size_t  id)
inline

Definition at line 1862 of file fastx_sequence_file.hpp.

1862 {
1863 std::unique_lock lock(mutex_);
1864 filled_.wait(lock, [&] { return results_[id].has_value() || errors_[id] != nullptr; });
1865 ++taken_;
1866 // One freed window slot needs one loader, not all of them: waking the rest is a syscall
1867 // and a context switch each, once per genome, at 100,000 genomes.
1868 assign_.notify_one();
1869 lock.unlock();
1870 if (errors_[id] != nullptr) std::rethrow_exception(errors_[id]);
1871 return std::move(*results_[id]);
1872 }

◆ take_ready()

Result< std::pair< size_t, std::unique_ptr< fastx_sequence_file > > > cuddl::detail::fastx_load_pool::take_ready ( )
inline

Definition at line 1874 of file fastx_sequence_file.hpp.

1874 {
1875 if (ready_.empty())
1876 return Err(Error::invalid_argument("completion-order loading is disabled"));
1877 std::unique_lock lock(mutex_);
1878 filled_.wait(lock, [&] { return ready_count_ != 0; });
1879 auto const id = ready_[ready_head_];
1880 ready_head_ = (ready_head_ + 1) % ready_.size();
1881 --ready_count_;
1882 ++taken_;
1883 assign_.notify_one();
1884 lock.unlock();
1885 if (errors_[id] != nullptr) std::rethrow_exception(errors_[id]);
1886 return std::pair{id, CUDDL_TRY(std::move(*results_[id]))};
1887 }
#define CUDDL_TRY(expr)
Propagates a cuddl::Result failure from the enclosing function (GNU statement expression).
Definition error.hpp:225
cuda::std::unexpected< Error > Err(Error error)
Failure return; converts to any Result<T> via cuda::std::unexpected.
Definition error.hpp:176
static Error invalid_argument(std::string message)
Definition error.hpp:99
Here is the call graph for this function:

◆ take_ready_until_limit()

Result< std::optional< std::pair< size_t, std::unique_ptr< fastx_sequence_file > > > > cuddl::detail::fastx_load_pool::take_ready_until_limit ( )
inline

take_ready, or nothing once every id below the cap limit is taken.

Definition at line 1891 of file fastx_sequence_file.hpp.

1891 {
1892 {
1893 std::unique_lock lock(mutex_);
1894 filled_.wait(lock, [&] { return ready_count_ != 0 || taken_ >= limit_; });
1895 if (ready_count_ == 0) return std::nullopt;
1896 }
1897 return CUDDL_TRY(take_ready());
1898 }
Result< std::pair< size_t, std::unique_ptr< fastx_sequence_file > > > take_ready()

The documentation for this class was generated from the following file: