Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions cpp/include/seqwin/graph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ struct Node {
/** Hash value of the minimizers represented by this node. */
std::uint64_t hash;
/** Start of the half-open range for this node's minimizer entries. */
std::uint64_t start;
std::size_t start;
/** End of the half-open range for this node's minimizer entries. */
std::uint64_t stop;
std::size_t stop;
/** Number of target assemblies containing this minimizer hash. */
std::uint32_t n_tar;
/** Number of non-target assemblies containing this minimizer hash. */
Expand All @@ -49,7 +49,7 @@ struct Edge {
/** Larger endpoint hash of the undirected edge. */
std::uint64_t second;
/** Number of assemblies where the endpoints are adjacent. */
std::uint64_t weight;
std::size_t weight;
};

/**
Expand All @@ -59,13 +59,13 @@ struct Graph {
/** Minimizer occurrences in all assemblies, grouped and sorted by hash. */
NoInitArray<Kmer> kmers;
/** Parallel to `kmers` and stores each minimizer's original generation index, ordered by genomic position. */
NoInitArray<std::uint64_t> idx;
NoInitArray<std::size_t> idx;
/** Sorted by hash. */
NoInitArray<Node> nodes;
/** Sorted by hash. */
NoInitArray<Edge> edges;
/** Cumulative global FASTA record offsets by assembly. */
std::vector<std::uint64_t> record_offsets;
std::vector<std::size_t> record_offsets;
/** FASTA record IDs of each assembly. */
std::vector<std::vector<std::string>> ids_by_assembly;
};
Expand Down
16 changes: 8 additions & 8 deletions cpp/include/seqwin/helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@ class ThreadPool;
/**
* @brief Thread-local minimizer graph node.
*
* The `[start, stop)` range is a half-open interval in `ThreadGraph.idx`.
* `start` and `count` define a range in `ThreadGraph.idx`.
* Values in `ThreadGraph.idx` index into `ThreadGraph.kmers`.
*/
struct ThreadNode {
/** Hash value of the minimizers represented by this node. */
std::uint64_t hash;
/** Start of the half-open range in `ThreadGraph.idx`. */
std::uint64_t start;
/** End of the half-open range in `ThreadGraph.idx`. */
std::uint64_t stop;
/** Start of entries in `ThreadGraph.idx` for this node. */
std::size_t start;
/** Number of entries in `ThreadGraph.idx` for this node. */
std::size_t count;
/** Number of target assemblies containing this minimizer hash. */
std::uint32_t n_tar;
/** Number of non-target assemblies containing this minimizer hash. */
Expand All @@ -46,13 +46,13 @@ struct ThreadGraph {
* The order is stable within each hash group, preserving the original genomic
* position order of minimizers with the same hash.
*/
NoInitArray<std::uint64_t> idx;
NoInitArray<std::size_t> idx;
/** Unsorted. */
NoInitArray<ThreadNode> nodes;
/** Unsorted. */
NoInitArray<Edge> edges;
/** Thread-local cumulative FASTA record offsets by assembly. */
std::vector<std::uint64_t> record_offsets;
std::vector<std::size_t> record_offsets;
/** FASTA record IDs of each assembly. */
std::vector<std::vector<std::string>> ids_by_assembly;
/** Total number of minimizers generated by this worker. */
Expand Down Expand Up @@ -88,7 +88,7 @@ Graph merge_thread_graphs(

Graph filter_kmers(
const Kmer* kmers,
const std::uint64_t* idx,
const std::size_t* idx,
const Node* nodes,
std::size_t n_nodes,
std::vector<std::uint64_t> used_hashes
Expand Down
4 changes: 2 additions & 2 deletions cpp/src/bindings/python_bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ PYBIND11_MODULE(_core, m) {

m.def("_filter_kmers_native",
[](py::array_t<seqwin::Kmer, py::array::c_style> kmers,
py::array_t<std::uint64_t, py::array::c_style> idx,
py::array_t<std::size_t, py::array::c_style> idx,
py::array_t<seqwin::Node, py::array::c_style> nodes,
const std::vector<std::uint64_t>& used_hashes
) {
Expand All @@ -99,7 +99,7 @@ PYBIND11_MODULE(_core, m) {
auto nodes_buf = nodes.request();

const auto* kmers_ptr = static_cast<const seqwin::Kmer*>(kmers_buf.ptr);
const auto* idx_ptr = static_cast<const std::uint64_t*>(idx_buf.ptr);
const auto* idx_ptr = static_cast<const std::size_t*>(idx_buf.ptr);
const auto* nodes_ptr = static_cast<const seqwin::Node*>(nodes_buf.ptr);
const auto n_nodes = static_cast<std::size_t>(nodes_buf.shape[0]);

Expand Down
17 changes: 8 additions & 9 deletions cpp/src/seqwin/graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ namespace {
constexpr std::size_t map_reserve_divisor = 100;

struct NodeState {
std::uint64_t count = 0;
std::uint64_t start = 0;
std::uint64_t cursor = 0;
std::size_t count = 0;
std::size_t start = 0;
std::size_t cursor = 0;
std::uint32_t n_tar = 0;
std::uint32_t n_neg = 0;
std::size_t last_seen_assembly = std::numeric_limits<std::size_t>::max();
Expand All @@ -39,7 +39,7 @@ struct EdgeKeyHash {
};

struct EdgeState {
std::uint64_t weight = 0;
std::size_t weight = 0;
std::size_t last_seen_assembly = std::numeric_limits<std::size_t>::max();
};

Expand Down Expand Up @@ -152,8 +152,8 @@ ThreadGraph build_worker(
std::unordered_map<EdgeKey, EdgeState, EdgeKeyHash>().swap(edge_map);

// Build ThreadGraph.idx (grouped by minimizer hash)
graph.idx = NoInitArray<std::uint64_t>(graph.n_kmers);
std::uint64_t cursor = 0;
graph.idx = NoInitArray<std::size_t>(graph.n_kmers);
std::size_t cursor = 0;
for (auto& [hash, state] : node_map) {
(void)hash;
state.start = cursor;
Expand All @@ -163,18 +163,17 @@ ThreadGraph build_worker(
for (std::size_t i = 0; i < graph.n_kmers; ++i) {
const auto hash = hashes[i];
auto node_it = node_map.find(hash);
graph.idx[node_it->second.cursor++] = static_cast<std::uint64_t>(i);
graph.idx[node_it->second.cursor++] = i;
}
std::vector<std::uint64_t>().swap(hashes);

graph.nodes = NoInitArray<ThreadNode>(node_map.size());
std::size_t node_i = 0;
for (const auto& [hash, state] : node_map) {
const auto stop = state.start + state.count;
graph.nodes[node_i++] = ThreadNode{
hash,
state.start,
stop,
state.count,
state.n_tar,
state.n_neg,
thread_id
Expand Down
71 changes: 34 additions & 37 deletions cpp/src/seqwin/helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ struct IdxSegment {
std::size_t thread_id;
std::size_t local_start;
std::size_t out_start;
std::size_t length;
std::size_t count;
};

template <typename T, typename MemberPtr>
Expand Down Expand Up @@ -75,7 +75,7 @@ static void lsd_radix_sort_key(
T*& dst,
std::size_t n,
KeyPtr key,
std::vector<std::uint64_t>& counts,
std::vector<std::size_t>& counts,
ThreadPool& pool
) {
static constexpr std::size_t bucket_count = 65536;
Expand All @@ -92,7 +92,7 @@ static void lsd_radix_sort_key(
}
});

std::uint64_t current = 0;
std::size_t current = 0;
for (std::size_t bucket = 0; bucket < bucket_count; ++bucket) {
for (std::size_t t = 0; t < pool.size(); ++t) {
auto& value = counts[t * bucket_count + bucket];
Expand Down Expand Up @@ -134,7 +134,7 @@ static void lsd_radix_sort(
NoInitArray<T> buf(n);
auto* src = values.data();
auto* dst = buf.data();
std::vector<std::uint64_t> counts(pool.size() * 65536);
std::vector<std::size_t> counts(pool.size() * 65536);

(lsd_radix_sort_key(src, dst, n, keys, counts, pool), ...);
}
Expand Down Expand Up @@ -177,7 +177,7 @@ static std::pair<NoInitArray<Node>, std::vector<IdxSegment>> merge_nodes(
std::vector<IdxSegment> idx_segments;
idx_segments.reserve(n_nodes);

std::uint64_t n_kmers = 0;
std::size_t n_kmers = 0;
std::size_t write_i = 0;
i = 0;
while (i < n_nodes) {
Expand All @@ -189,19 +189,16 @@ static std::pair<NoInitArray<Node>, std::vector<IdxSegment>> merge_nodes(
while (i < n_nodes && nodes[i].hash == hash) {
n_tar += nodes[i].n_tar;
n_neg += nodes[i].n_neg;
const auto count = nodes[i].count;

const auto local_start = nodes[i].start;
const auto local_stop = nodes[i].stop;
const auto length = local_stop - local_start;

if (length != 0) {
if (count != 0) {
idx_segments.push_back(IdxSegment{
nodes[i].thread_id,
static_cast<std::size_t>(local_start),
static_cast<std::size_t>(n_kmers),
static_cast<std::size_t>(length)
nodes[i].start,
n_kmers,
count
});
n_kmers += length;
n_kmers += count;
}
++i;
}
Expand All @@ -216,7 +213,7 @@ static NoInitArray<Kmer> merge_kmers(
const std::vector<ThreadGraph>& graphs,
std::size_t total_kmers,
const std::vector<IdxSegment>& idx_segments,
const std::vector<std::uint64_t>& thread_record_offsets,
const std::vector<std::size_t>& thread_record_offsets,
ThreadPool& pool
) {
NoInitArray<Kmer> kmers(total_kmers);
Expand All @@ -228,9 +225,9 @@ static NoInitArray<Kmer> merge_kmers(
const auto& local_kmers = graphs[segment.thread_id].kmers;
const auto offset = thread_record_offsets[segment.thread_id];

for (std::size_t k = 0; k < segment.length; ++k) {
for (std::size_t k = 0; k < segment.count; ++k) {
const auto local_kmer_i = local_idx[segment.local_start + k];
auto kmer = local_kmers[static_cast<std::size_t>(local_kmer_i)];
auto kmer = local_kmers[local_kmer_i];
kmer.record_idx += static_cast<std::uint32_t>(offset);
kmers[segment.out_start + k] = kmer;
}
Expand All @@ -239,22 +236,22 @@ static NoInitArray<Kmer> merge_kmers(
return kmers;
}

static NoInitArray<std::uint64_t> merge_idx(
static NoInitArray<std::size_t> merge_idx(
const std::vector<ThreadGraph>& graphs,
std::size_t total_kmers,
const std::vector<IdxSegment>& idx_segments,
const std::vector<std::uint64_t>& kmer_offsets,
const std::vector<std::size_t>& kmer_offsets,
ThreadPool& pool
) {
NoInitArray<std::uint64_t> idx(total_kmers);
NoInitArray<std::size_t> idx(total_kmers);

pool.parallel_for(idx_segments.size(), [&](std::size_t start, std::size_t end, std::size_t) {
for (std::size_t s = start; s < end; ++s) {
const auto& segment = idx_segments[s];
const auto offset = kmer_offsets[segment.thread_id];
const auto& local_idx = graphs[segment.thread_id].idx;

for (std::size_t k = 0; k < segment.length; ++k) {
for (std::size_t k = 0; k < segment.count; ++k) {
idx[segment.out_start + k] = local_idx[segment.local_start + k] + offset;
}
}
Expand Down Expand Up @@ -290,7 +287,7 @@ static void merge_edges(NoInitArray<Edge>& edges, ThreadPool& pool)
while (i < n_edges) {
const auto first = edges[i].first;
const auto second = edges[i].second;
std::uint64_t weight = 0;
std::size_t weight = 0;

while (i < n_edges && edges[i].first == first && edges[i].second == second) {
weight += edges[i].weight;
Expand Down Expand Up @@ -341,7 +338,7 @@ Graph merge_thread_graphs(
auto [nodes, idx_segments] = merge_nodes(graph.nodes, pool);
graph.nodes.reset();

std::vector<std::uint64_t> thread_record_offsets{0};
std::vector<std::size_t> thread_record_offsets{0};
auto kmers = merge_kmers(
graphs,
graph.n_kmers,
Expand All @@ -351,7 +348,7 @@ Graph merge_thread_graphs(
);
std::vector<Kmer>().swap(graph.kmers);

std::vector<std::uint64_t> kmer_offsets{0};
std::vector<std::size_t> kmer_offsets{0};
auto idx = merge_idx(
graphs,
graph.n_kmers,
Expand All @@ -375,12 +372,12 @@ Graph merge_thread_graphs(
log_python(" - Merging from " + std::to_string(graphs.size()) + " threads...");

// Merge record offsets
std::vector<std::uint64_t> thread_record_offsets(graphs.size());
std::vector<std::uint64_t> record_offsets;
std::vector<std::size_t> thread_record_offsets(graphs.size());
std::vector<std::size_t> record_offsets;
record_offsets.reserve(n_assemblies + 1);
record_offsets.push_back(0);

std::uint64_t total_records = 0;
std::size_t total_records = 0;
for (std::size_t t = 0; t < graphs.size(); ++t) {
auto& local_offsets = graphs[t].record_offsets;

Expand All @@ -391,7 +388,7 @@ Graph merge_thread_graphs(
for (std::size_t i = 1; i < local_offsets.size(); ++i) {
record_offsets.push_back(base + local_offsets[i]);
}
std::vector<std::uint64_t>().swap(local_offsets);
std::vector<std::size_t>().swap(local_offsets);
}
if (total_records > std::numeric_limits<std::uint32_t>::max()) {
throw std::runtime_error("Total number of FASTA records exceeds uint32 range");
Expand All @@ -405,8 +402,8 @@ Graph merge_thread_graphs(
auto [nodes, idx_segments] = merge_nodes(thread_nodes, pool);
thread_nodes.reset();

std::vector<std::uint64_t> kmer_offsets(graphs.size());
std::uint64_t total_kmers = 0;
std::vector<std::size_t> kmer_offsets(graphs.size());
std::size_t total_kmers = 0;
for (std::size_t t = 0; t < graphs.size(); ++t) {
kmer_offsets[t] = total_kmers;
total_kmers += graphs[t].n_kmers;
Expand Down Expand Up @@ -445,7 +442,7 @@ Graph merge_thread_graphs(

Graph filter_kmers(
const Kmer* kmers,
const std::uint64_t* idx,
const std::size_t* idx,
const Node* nodes,
std::size_t n_nodes,
std::vector<std::uint64_t> used_hashes
Expand Down Expand Up @@ -474,16 +471,16 @@ Graph filter_kmers(
}

used_node_indices.push_back(node_i);
n_kmers += static_cast<std::size_t>(nodes[node_i].stop - nodes[node_i].start);
n_kmers += nodes[node_i].stop - nodes[node_i].start;
++node_i;
++used_i;
}

graph.nodes = NoInitArray<Node>(used_node_indices.size());
graph.kmers = NoInitArray<Kmer>(n_kmers);
graph.idx = NoInitArray<std::uint64_t>(n_kmers);
graph.idx = NoInitArray<std::size_t>(n_kmers);

std::uint64_t new_start = 0;
std::size_t new_start = 0;
for (std::size_t out_node_i = 0; out_node_i < used_node_indices.size(); ++out_node_i) {
const auto in_node_i = used_node_indices[out_node_i];
const Node& old_node = nodes[in_node_i];
Expand All @@ -497,9 +494,9 @@ Graph filter_kmers(
new_node.stop = new_start + size;
graph.nodes[out_node_i] = new_node;

for (std::uint64_t k = 0; k < size; ++k) {
const auto out_i = static_cast<std::size_t>(new_start + k);
const auto in_i = static_cast<std::size_t>(old_start + k);
for (std::size_t k = 0; k < size; ++k) {
const auto out_i = new_start + k;
const auto in_i = old_start + k;
graph.kmers[out_i] = kmers[in_i];
graph.idx[out_i] = idx[in_i];
}
Expand Down
Loading
Loading