Skip to content

Commit 4389236

Browse files
authored
Merge pull request #428 from pgangwar-ucsd/usher_server_build
Usher server build and runtime fix
2 parents a87e940 + f188cb0 commit 4389236

6 files changed

Lines changed: 69 additions & 69 deletions

File tree

CMakeLists.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -571,9 +571,10 @@ if(NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin")
571571
endif()
572572

573573
if(USHER_SERVER)
574+
target_include_directories(usher-sampled-server PUBLIC taskflow)
574575
TARGET_COMPILE_OPTIONS(usher_server PRIVATE)
575-
TARGET_LINK_LIBRARIES(usher_server PRIVATE stdc++ ${Boost_LIBRARIES} TBB::tbb ${Protobuf_LIBRARIES} ZLIB::ZLIB) # OpenMP::OpenMP_CXX)
576-
TARGET_LINK_LIBRARIES(usher-sampled-server PRIVATE stdc++ ${CMAKE_DL_LIBS} ${Boost_LIBRARIES} TBB::tbb ${Protobuf_LIBRARIES} ZLIB::ZLIB ${MPI_CXX_LIBRARIES} ${MPI_CXX_LINK_FLAGS} ${ISAL_LIB} ) # OpenMP::OpenMP_CXX)
576+
TARGET_LINK_LIBRARIES(usher_server PRIVATE stdc++ ${Boost_LIBRARIES} TBB::tbb TBB::tbbmalloc ${Protobuf_LIBRARIES} ZLIB::ZLIB) # OpenMP::OpenMP_CXX)
577+
TARGET_LINK_LIBRARIES(usher-sampled-server PRIVATE stdc++ ${CMAKE_DL_LIBS} ${Boost_LIBRARIES} TBB::tbb TBB::tbbmalloc ${Protobuf_LIBRARIES} ZLIB::ZLIB ${MPI_CXX_LIBRARIES} ${MPI_CXX_LINK_FLAGS} ${ISAL_LIB} ) # OpenMP::OpenMP_CXX)
577578
install(TARGETS usher matUtils matOptimize ripples usher_server DESTINATION bin)
578579
else()
579580
install(TARGETS usher matUtils matOptimize ripples DESTINATION bin)

src/usher-sampled/driver/socket.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <atomic>
44
#include <boost/filesystem/operations.hpp>
55
#include <boost/filesystem/path.hpp>
6+
#include <boost/filesystem.hpp>
67
#include <boost/program_options.hpp>
78
#include <boost/program_options/value_semantic.hpp>
89
#include <cerrno>
@@ -114,7 +115,6 @@ void reload_trees(TreeCollectionPtr &to_replace, const std::vector<std::string>&
114115
}
115116
}
116117
to_replace.reset(next);
117-
init.terminate();
118118
fprintf(stderr, "finish loading the tree\n");
119119
}
120120
void refresh_tree(TreeCollectionPtr &to_replace, std::fstream &tree_paths) {
@@ -583,7 +583,6 @@ static void tree_update_watch(int refresh_period, std::mutex& done_mutex,std::co
583583
}
584584
}
585585
}
586-
init.terminate();
587586
}
588587
}
589588
}

src/usher-sampled/import_vcf.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,6 @@ static void process(infile_t &fd, std::vector<Sample_Muts> &sample_mutations,
498498
read_size = first_approx_size * single_line_size;
499499
alloc_size = (first_approx_size + 2) * single_line_size;
500500
tbb::concurrent_bounded_queue<std::pair<char *, uint8_t *>> queue;
501-
queue.set_capacity(10);
502501
tbb::flow::input_node<line_start_later> line(input_graph, line_align(queue));
503502
tbb::flow::make_edge(line, parser);
504503
line.activate();

src/usher-sampled/main_mapper.cpp

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#include <cstdio>
88
#include <signal.h>
99
#include <tbb/parallel_for.h>
10-
#include <tbb/task_group.h>
10+
#include <taskflow/taskflow.hpp>
1111
#include <unordered_map>
1212
#include <utility>
1313
#include <vector>
@@ -378,7 +378,7 @@ struct Main_Tree_Searcher {
378378
#ifdef DETAILED_MERGER_CHECK
379379
Mutation_Set &sample_mutations;
380380
#endif
381-
Main_Tree_Searcher(int curr_lower_bound,MAT::Node *node,
381+
Main_Tree_Searcher(int curr_lower_bound, const MAT::Node *node,
382382
Output<Main_Tree_Target> &output
383383
#ifdef DETAILED_MERGER_CHECK
384384
,
@@ -393,8 +393,7 @@ struct Main_Tree_Searcher {
393393
#endif
394394
{
395395
}
396-
void execute() {
397-
tbb::task_group tg;
396+
void operator()(tf::Subflow& sf) {
398397
#ifndef BOUND_CHECK
399398
if(curr_lower_bound>output.best_par_score) {
400399
return;
@@ -404,8 +403,10 @@ struct Main_Tree_Searcher {
404403
search_serial(node, this_muts, output);
405404
return;
406405
}
407-
std::vector<Main_Tree_Searcher> children_tasks;
408-
children_tasks.reserve(node->children.size() + 1);
406+
auto* output_ptr = &output;
407+
#ifdef DETAILED_MERGER_CHECK
408+
auto* samples_ptr = &sample_mutations;
409+
#endif
409410
Main_Tree_Target target;
410411
for (const auto child : node->children) {
411412
target.target_node = child;
@@ -434,14 +435,20 @@ struct Main_Tree_Searcher {
434435
#ifndef BOUND_CHECK
435436
if (lower_bound <= output.best_par_score) {
436437
#endif
437-
children_tasks.emplace_back(lower_bound, child, output
438+
sf.emplace([=, muts = std::move(descendant_mutations)
438439
#ifdef DETAILED_MERGER_CHECK
439440
,
440441
sample_mutations
441442
#endif
442-
);
443-
children_tasks.back().this_muts =
444-
std::move(descendant_mutations);
443+
](tf::Subflow& child_sf) mutable {
444+
Main_Tree_Searcher child_searcher(lower_bound, child, *output_ptr
445+
#ifdef DETAILED_MERGER_CHECK
446+
, *samples_ptr
447+
#endif
448+
);
449+
child_searcher.this_muts = std::move(muts);
450+
child_searcher(child_sf);
451+
});
445452
#ifndef BOUND_CHECK
446453
}
447454
#endif
@@ -452,12 +459,6 @@ struct Main_Tree_Searcher {
452459
assert(parsimony_score>=curr_lower_bound);
453460
register_target(target, parsimony_score,output);
454461
}
455-
for (auto& child : children_tasks) {
456-
tg.run([&child]{
457-
child.execute();
458-
});
459-
}
460-
tg.wait();
461462
}
462463
};
463464

@@ -487,21 +488,25 @@ place_main_tree(const std::vector<To_Place_Sample_Mutation> &mutations,
487488
}
488489
}
489490
output.targets.push_back(target);
490-
std::vector<To_Place_Sample_Mutation> initial_muts = mutations;
491-
initial_muts.push_back(temp);
492491

493-
Main_Tree_Searcher main_tree_task_root{0,main_tree.root,
492+
tf::Executor executor;
493+
tf::Taskflow taskflow;
494+
495+
taskflow.emplace([&](tf::Subflow& sf) {
496+
Main_Tree_Searcher root_searcher(0,main_tree.root,
494497
output
495498
#ifdef DETAILED_MERGER_CHECK
496499
,
497500
sample_mutations
498501
#endif
499-
};
500-
main_tree_task_root.this_muts = mutations;
501-
main_tree_task_root.this_muts.push_back(temp);
502-
main_tree_task_root.execute();
502+
);
503+
root_searcher.this_muts = mutations;
504+
root_searcher.this_muts.push_back(temp);
505+
root_searcher(sf);
506+
});
507+
508+
executor.run(taskflow).wait();
503509

504510
assert(!output.targets.empty());
505-
506511
return std::make_tuple(std::move(output.targets), output.best_par_score);
507512
}

src/usher-sampled/sampler.cpp

Lines changed: 34 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <unordered_map>
77
#include <vector>
88
#include <taskflow/taskflow.hpp>
9+
#include <memory>
910

1011
namespace MAT = Mutation_Annotated_Tree;
1112

@@ -51,53 +52,48 @@ struct Assign_Descendant_Possible_Muts_Cont {
5152
}
5253
};
5354

54-
struct Assign_Descendant_Possible_Muts {
55-
tf::Taskflow& taskflow;
56-
MAT::Node *root;
57-
std::unordered_map<int, uint8_t> &output;
58-
Assign_Descendant_Possible_Muts(tf::Taskflow& t, MAT::Node *root,
59-
std::unordered_map<int, uint8_t> &output)
60-
: taskflow{t}, root(root), output(output) {}
61-
void execute() const {
62-
Assign_Descendant_Possible_Muts_Cont cont(output, root->children.size(),
63-
root);
64-
std::vector<Assign_Descendant_Possible_Muts> children_tasks;
65-
children_tasks.reserve(root->children.size());
66-
for (size_t idx = 0; idx < root->children.size(); idx++) {
67-
auto this_child = root->children[idx];
68-
if (this_child->children.empty()) {
69-
cont.children_out[idx].reserve(this_child->mutations.size());
70-
for (auto &mut : this_child->mutations) {
71-
mut.set_descendant_mut(mut.get_mut_one_hot());
72-
cont.children_out[idx].emplace(mut.get_position(),
73-
mut.get_mut_one_hot());
74-
}
75-
} else {
76-
children_tasks.emplace_back(taskflow,
77-
this_child, cont.children_out[idx]);
55+
void build_task_graph(MAT::Node* node, std::unordered_map<int, uint8_t>& output, tf::Subflow& subflow) {
56+
// 1. Allocate Context on the HEAP (Safety Fix)
57+
auto cont_ptr = std::make_shared<Assign_Descendant_Possible_Muts_Cont>(output, node->children.size(), node);
58+
59+
// 2. Create Continuation Task
60+
tf::Task continuation = subflow.emplace([cont_ptr]() {
61+
cont_ptr->execute();
62+
});
63+
64+
// 3. Spawn Children
65+
for (size_t i = 0; i < node->children.size(); ++i) {
66+
auto child = node->children[i];
67+
68+
if (child->children.empty()) {
69+
// Leaf optimization (Serial execution)
70+
cont_ptr->children_out[i].reserve(child->mutations.size());
71+
for (auto &mut : child->mutations) {
72+
mut.set_descendant_mut(mut.get_mut_one_hot());
73+
cont_ptr->children_out[i].emplace(mut.get_position(), mut.get_mut_one_hot());
7874
}
79-
}
80-
if (children_tasks.empty()) {
81-
cont.execute();
8275
} else {
83-
taskflow.emplace([&children_tasks](tf::Subflow& subflow){
84-
for (auto&& child_task : std::move(children_tasks)) {
85-
subflow.emplace([child_task = std::move(child_task)] {
86-
child_task.execute();
87-
});
88-
}
76+
// Recursion: Create a subflow for the child
77+
// Capture 'cont_ptr' and 'i' by value to be safe
78+
tf::Task child_task = subflow.emplace([child, cont_ptr, i](tf::Subflow& sf) {
79+
build_task_graph(child, cont_ptr->children_out[i], sf);
80+
});
8981

90-
});
82+
// The continuation (execute) must wait for the child to finish
83+
child_task.precede(continuation);
9184
}
9285
}
93-
};
86+
}
9487

88+
// Entry Point
9589
void assign_descendant_muts(MAT::Tree &in) {
9690
std::unordered_map<int, uint8_t> ignore;
9791
tf::Executor executor;
9892
tf::Taskflow taskflow;
99-
taskflow.emplace([&] {
100-
Assign_Descendant_Possible_Muts(taskflow, in.root, ignore).execute();
93+
94+
taskflow.emplace([&](tf::Subflow& subflow) {
95+
build_task_graph(in.root, ignore, subflow);
10196
});
97+
10298
executor.run(taskflow).wait();
103-
}
99+
}

src/usher_server.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ int main(int argc, char** argv) {
3030
//Variables to load command-line options using Boost program_options
3131
std::string arg_dirname;
3232
std::string MAT_list_filename;
33-
uint32_t num_cores = tbb::task_scheduler_init::default_num_threads();
33+
uint32_t num_cores = tbb::global_control::active_value(tbb::global_control::max_allowed_parallelism);
3434
po::options_description desc{"Options"};
3535
uint32_t sleep_length;
3636
uint32_t termination_character;
@@ -81,7 +81,7 @@ int main(int argc, char** argv) {
8181
// timer object to be used to measure runtimes of individual stages
8282
Timer timer;
8383
fprintf(stderr, "Initializing %u worker threads.\n\n", num_threads);
84-
tbb::task_scheduler_init init(num_threads);
84+
tbb::global_control global_limit(tbb::global_control::max_allowed_parallelism, num_threads);
8585

8686

8787
//MAT that is used in the iteration

0 commit comments

Comments
 (0)