cuDDL
Loading...
Searching...
No Matches
Classes | Public Types | Public Member Functions | Static Public Member Functions | List of all members
cuddl::replicated_database< K, BucketCount, Layout > Class Template Reference

One reference database replicated on explicitly chosen devices, searched all-to-all by all of them at once. More...

Public Types

using database_type = reference_database< K, BucketCount, Layout >
 
using index_type = reference_index< K, BucketCount, Layout >
 

Public Member Functions

Result< void > build_index (index_storage storage=index_storage::automatic)
 Builds an index on every replica.
 
Result< void > load_index (std::filesystem::path const &path)
 Loads the index file at path onto every replica.
 
template<typename OnTile >
Result< void > search_all_to_all (OnTile &&on_tile, replica_search split={})
 Exhaustively searches every unique database-row pair in split.shard on all replicas.
 
template<typename OnTile >
Result< void > search_all_to_all (OnTile &&on_tile, search_options options, replica_search split={})
 Threshold search of every unique pair in split.shard: pairs with at least options.minimum_matches matches, through each replica's index when one is loaded.
 
size_t size () const noexcept
 Number of replicas, one per device.
 
std::vector< cuda::device_ref > devices () const
 The devices, in replica order.
 
database_type const & database () const noexcept
 The database every replica holds, as uploaded to replica 0.
 

Static Public Member Functions

static Result< replicated_database > upload (reference_database_file const &file, std::span< cuda::device_ref const > devices)
 Uploads file to each of devices, concurrently.
 
static Result< replicated_database > adopt (std::vector< database_type > databases)
 Adopts databases that already hold identical rows, one per device, each searched on the device that built it (reference_database::device).
 

Detailed Description

template<uint32_t K, size_t BucketCount, typename Layout = default_register_layout>
class cuddl::replicated_database< K, BucketCount, Layout >

One reference database replicated on explicitly chosen devices, searched all-to-all by all of them at once.

Each device gets a replica with its own stream, result storage, optional index, and pinned host memory on the device's host NUMA node, so downloads stay off the socket interconnect. A search runs one host thread per replica. Replicas claim tiles from one all_to_all_tile_queue, largest first, so devices of different speeds share the work: a faster device simply claims more. Kernels pick their launch shapes from each device's own properties, so the devices may differ in architecture and memory size; each needs room for the rows and its result storage, and a device without it fails the search with its error.

To split a search across processes, for example MPI ranks on several nodes, give each process its own group and pass every process a different all_to_all_shard. To let processes of different speeds share the work, also pass every process the same next_tile counter, such as a shared_tile_counter from distributed.cuh; there, cuddl::search_all_to_all sets both up from an MPI communicator.

Definition at line 72 of file replicated_database.cuh.

Member Typedef Documentation

◆ database_type

template<uint32_t K, size_t BucketCount, typename Layout = default_register_layout>
using cuddl::replicated_database< K, BucketCount, Layout >::database_type = reference_database<K, BucketCount, Layout>

Definition at line 74 of file replicated_database.cuh.

◆ index_type

template<uint32_t K, size_t BucketCount, typename Layout = default_register_layout>
using cuddl::replicated_database< K, BucketCount, Layout >::index_type = reference_index<K, BucketCount, Layout>

Definition at line 75 of file replicated_database.cuh.

Member Function Documentation

◆ adopt()

template<uint32_t K, size_t BucketCount, typename Layout = default_register_layout>
static Result< replicated_database > cuddl::replicated_database< K, BucketCount, Layout >::adopt ( std::vector< database_type >  databases)
inlinestatic

Adopts databases that already hold identical rows, one per device, each searched on the device that built it (reference_database::device).

The streams that built them must outlive the group.

Definition at line 91 of file replicated_database.cuh.

91 {
92 std::vector<cuda::device_ref> devices;
93 for (auto const& database : databases) {
94 if (database.metadata() != databases.front().metadata()) {
95 return Err(Error::invalid_argument("replicas must share their database metadata"));
96 }
97 devices.push_back(database.device());
98 }
99 auto group = CUDDL_TRY(make(devices));
100 for (size_t i = 0; i < databases.size(); ++i) {
101 group.replicas_[i]->database.emplace(std::move(databases[i]));
102 }
103 return Result<replicated_database>::ok(std::move(group));
104 }
reference_database_metadata metadata() const noexcept
Compatibility metadata and reference count.
cuda::device_ref device() const noexcept
Device holding the rows: the device of the stream that built them.
database_type const & database() const noexcept
The database every replica holds, as uploaded to replica 0.
std::vector< cuda::device_ref > devices() const
The devices, in replica order.
#define CUDDL_TRY(expr)
Propagates a cuddl::Result failure from the enclosing function (GNU statement expression).
Definition error.hpp:225
constexpr uint32_t group
Definition kernels.cuh:1858
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
static Result ok(T value)
Definition error.hpp:121
Here is the call graph for this function:

◆ build_index()

template<uint32_t K, size_t BucketCount, typename Layout = default_register_layout>
Result< void > cuddl::replicated_database< K, BucketCount, Layout >::build_index ( index_storage  storage = index_storage::automatic)
inline

Builds an index on every replica.

Definition at line 107 of file replicated_database.cuh.

107 {
108 return on_each([&](replica& r, uint32_t) -> Result<void> {
109 r.index.emplace(CUDDL_TRY(index_type::build_async(*r.database, r.stream, storage)));
110 r.stream.sync();
111 return Ok();
112 });
113 }
static Result< reference_index > build_async(database_type const &database, cuda::stream_ref stream, index_storage storage=index_storage::automatic)
Build acceleration data without taking ownership of or copying reference rows.
Result< void > Ok() noexcept
Success return for Result<void>; same as return {}.
Definition error.hpp:181
Here is the call graph for this function:

◆ database()

template<uint32_t K, size_t BucketCount, typename Layout = default_register_layout>
database_type const & cuddl::replicated_database< K, BucketCount, Layout >::database ( ) const
inlinenoexcept

The database every replica holds, as uploaded to replica 0.

Definition at line 160 of file replicated_database.cuh.

160 {
161 return *replicas_.front()->database;
162 }
Here is the caller graph for this function:

◆ devices()

template<uint32_t K, size_t BucketCount, typename Layout = default_register_layout>
std::vector< cuda::device_ref > cuddl::replicated_database< K, BucketCount, Layout >::devices ( ) const
inline

The devices, in replica order.

Definition at line 153 of file replicated_database.cuh.

153 {
154 std::vector<cuda::device_ref> devices;
155 for (auto const& r : replicas_) devices.push_back(r->stream.device());
156 return devices;
157 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ load_index()

template<uint32_t K, size_t BucketCount, typename Layout = default_register_layout>
Result< void > cuddl::replicated_database< K, BucketCount, Layout >::load_index ( std::filesystem::path const &  path)
inline

Loads the index file at path onto every replica.

Definition at line 116 of file replicated_database.cuh.

116 {
117 return on_each([&](replica& r, uint32_t) -> Result<void> {
118 r.index.emplace(CUDDL_TRY(reference_index_file::load(path, *r.database, r.stream)));
119 return Ok();
120 });
121 }
static Result< reference_index< K, BucketCount, Layout > > load(std::filesystem::path const &path, reference_database< K, BucketCount, Layout > const &database, cuda::stream_ref stream)
Validate the file and its database binding once, then restore a ready-to-search index.
Here is the call graph for this function:

◆ search_all_to_all() [1/2]

template<uint32_t K, size_t BucketCount, typename Layout = default_register_layout>
template<typename OnTile >
Result< void > cuddl::replicated_database< K, BucketCount, Layout >::search_all_to_all ( OnTile &&  on_tile,
replica_search  split = {} 
)
inline

Exhaustively searches every unique database-row pair in split.shard on all replicas.

on_tile receives each tile as a replica_tile. By default replicas call it concurrently from their own threads, in no particular order, so it must be thread-safe; with split.in_query_order they call it one tile at a time in increasing query order. Like the single-database search, it must consume the tile before returning or enqueue dependent work on the tile's stream. An exception from on_tile stops every replica and is rethrown here.

Definition at line 135 of file replicated_database.cuh.

135 {}) {
136 return search(on_tile, split, std::nullopt);
137 }

◆ search_all_to_all() [2/2]

template<uint32_t K, size_t BucketCount, typename Layout = default_register_layout>
template<typename OnTile >
Result< void > cuddl::replicated_database< K, BucketCount, Layout >::search_all_to_all ( OnTile &&  on_tile,
search_options  options,
replica_search  split = {} 
)
inline

Threshold search of every unique pair in split.shard: pairs with at least options.minimum_matches matches, through each replica's index when one is loaded.

Definition at line 143 of file replicated_database.cuh.

143 {}) {
144 return search(on_tile, split, options);
145 }

◆ size()

template<uint32_t K, size_t BucketCount, typename Layout = default_register_layout>
size_t cuddl::replicated_database< K, BucketCount, Layout >::size ( ) const
inlinenoexcept

Number of replicas, one per device.

Definition at line 148 of file replicated_database.cuh.

148 {
149 return replicas_.size();
150 }

◆ upload()

template<uint32_t K, size_t BucketCount, typename Layout = default_register_layout>
static Result< replicated_database > cuddl::replicated_database< K, BucketCount, Layout >::upload ( reference_database_file const &  file,
std::span< cuda::device_ref const >  devices 
)
inlinestatic

Uploads file to each of devices, concurrently.

Definition at line 79 of file replicated_database.cuh.

79 {
80 auto group = CUDDL_TRY(make(devices));
81 CUDDL_TRY(group.on_each([&](replica& r, uint32_t) -> Result<void> {
82 r.database.emplace(CUDDL_TRY((file.upload<K, BucketCount, Layout>(r.stream))));
83 return Ok();
84 }));
85 return Result<replicated_database>::ok(std::move(group));
86 }
Here is the call graph for this function:

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