/* Template implementations for thortree.h. */ //------------------------------------------------------------------------- // IMPLEMENTATION //------------------------------------------------------------------------- //-- ThorTree template template void ThorTree::CreateResultCacheMaster( int channel, const Result& default_result, double megs, DistributedCache *results) { DEBUG_ASSERT_MSG(rpc::rank() == 0, "Only master calls this"); index_t block_size = CacheArray::GetNumBlockElements(points_); CacheArray::CreateCacheMaster(channel, block_size, default_result, megs, results); for (int i = 0; i < rpc::n_peers(); i++) { const TreeGrain *grain = &decomp_.grain_by_owner(i); if (grain->is_valid()) { BlockDevice::blockid_t begin_block = (grain->point_begin_index + block_size - 1) / block_size; BlockDevice::blockid_t end_block = (grain->point_end_index + block_size - 1) / block_size; DEBUG_ASSERT(results->n_blocks() == begin_block); results->AllocBlocks(end_block - begin_block, i); } } results->StartSync(); results->WaitSync(); } template template void ThorTree::CreateResultCacheWorker( int channel, double megs, DistributedCache *results) { DEBUG_ASSERT_MSG(rpc::rank() != 0, "Only workers call this"); CacheArray::CreateCacheWorker(channel, megs, results); results->StartSync(); results->WaitSync(); } template template void ThorTree::CreateResultCache( int channel, const Result& default_result, double megs, DistributedCache *results) { if (rpc::rank() == 0) { CreateResultCacheMaster(channel, default_result, megs, results); } else { CreateResultCacheWorker(channel, megs, results); } } template template void ThorTree::Update( DistributedCache *results_cache, Visitor *visitor) { ThorUpdate updater; updater.Doit(rpc::rank(), ¶m_, decomp_, visitor, results_cache, points_, nodes_); } //-- ThorTreeDecomposition template void ThorTreeDecomposition::FillLinearization_(DecompNode *node) { TreeGrain *grain; if (node->info().is_singleton() || !node->is_complete()) { grain = &grain_by_owner_[node->info().begin_rank]; grain->Init(*node); } else { for (int k = 0; k < Node::CARDINALITY; k++) { FillLinearization_(node->child(k)); } } } //-- ThorUpdate template void ThorUpdate::Doit( int my_rank, const Param *param, const TreeDecomposition& decomp, Visitor *visitor, DistributedCache *results_cache, DistributedCache *points_cache, DistributedCache *nodes_cache) { bool is_main_machine = (my_rank == decomp.root()->info().begin_rank); param_ = param; visitor_ = visitor; // Find my machine by searching the tree TreeGrain my_grain = decomp.grain_by_owner(my_rank); if (my_grain.is_valid()) { // I get a work item (this is always the case unlses for some reason // the tree is incredibly small) results_ = new CacheArray(); results_->Init(results_cache, BlockDevice::M_MODIFY, my_grain.point_begin_index, my_grain.point_end_index); points_ = new CacheArray(); points_->Init(points_cache, BlockDevice::M_MODIFY, my_grain.point_begin_index, my_grain.point_end_index); nodes_ = new CacheArray(); nodes_->Init(nodes_cache, BlockDevice::M_MODIFY, my_grain.node_index, my_grain.node_end_index); Recurse_(my_grain.node_index, NULL); delete results_; delete nodes_; delete points_; } nodes_ = NULL; points_ = NULL; results_ = NULL; nodes_cache->StartSync(); points_cache->StartSync(); nodes_cache->WaitSync(); if (is_main_machine) { // I'm the master machine! I update the top part of the tree! WOOT! nodes_ = new CacheArray(); // NOTE: M_APPEND actually means that writes to blocks are exclusive nodes_->Init(nodes_cache, BlockDevice::M_APPEND); Assemble_(decomp.root(), NULL); delete nodes_; } nodes_cache->StartSync(); nodes_cache->WaitSync(); points_cache->WaitSync(); } template void ThorUpdate::Assemble_( const DecompNode *decomp, Node *parent) { // We're at a leaf in the decomposition tree. Just update our parent. CacheWrite node(nodes_, decomp->index()); DEBUG_ASSERT(decomp->index() >= 0); if (decomp->is_complete() && !decomp->info().is_singleton()) { // The node has children in the decomposition tree, so they haven't been // updated. node->stat().Reset(*param_); for (int k = 0; k < Node::CARDINALITY; k++) { Assemble_(decomp->child(k), node); } } if (likely(parent != NULL)) { parent->stat().Accumulate(*param_, node->stat(), node->bound(), node->count()); } node->stat().Postprocess(*param_, node->bound(), node->count()); } template void ThorUpdate::Recurse_( index_t node_index, Node *parent) { CacheWrite node(nodes_, node_index); node->stat().Reset(*param_); node->bound().Reset(); if (!node->is_leaf()) { for (int k = 0; k < Node::CARDINALITY; k++) { Recurse_(node->child(k), node); } } else { CacheWriteIter result(results_, node->begin()); CacheWriteIter point(points_, node->begin()); for (index_t i = node->begin(); i < node->end(); i++, point.Next(), result.Next()) { visitor_->Update(i, point, result); node->stat().Accumulate(*param_, *point); node->bound() |= point->vec(); } } if (likely(parent != NULL)) { parent->stat().Accumulate( *param_, node->stat(), node->bound(), node->count()); parent->bound() |= node->bound(); node->stat().Postprocess(*param_, node->bound(), node->count()); } }