/** * @file thor_utils.h * * Top-level THOR utilities that take care of more high-level actions. * * This contains functions to read data and to execute a generalized N-body * problem in parallel. */ #ifndef THOR_UTILS_H #define THOR_UTILS_H #include "kdtree.h" #include "sched.h" #include "rpc.h" #include "par/thread.h" #include "par/task.h" #include "distribcache.h" namespace thor { /** * Class used to run a multi-threaded dual-tree algorithm. * * It is probably easier to use thor::RpcDualTree even if you are on just * one machine, and it's no more or less efficient either way. * * Template paramters: * @li GNP - the THOR-compatible generalized N-body class * @li Solver - a solver such as DualTreeDepthFirst<GNP> */ template class ThreadedDualTreeSolver { private: struct WorkerTask : public Task { ThreadedDualTreeSolver *solver; WorkerTask(ThreadedDualTreeSolver *solver_in) : solver(solver_in) { } void Run() { solver->ThreadBody_(); delete this; } }; private: int rank_; const typename GNP::Param *param_; SchedulerInterface *work_queue_; DistributedCache *q_points_cache_; DistributedCache *q_nodes_cache_; DistributedCache *r_points_cache_; DistributedCache *r_nodes_cache_; DistributedCache *q_results_cache_; typename GNP::GlobalResult global_result_; DualTreeRecursionStats stats_; Mutex mutex_; public: /** * Runs a multi-threaded dual-tree problem. * * @param n_threads the number of threads to run on this machine * @param rank the rank of the current machine (rpc::rank() will provide * this if RPC is being used, otherwise just specify 0) * @param work_queue_in the work queue to get work items from * @param param the parameter object for the GNP * @param q_points_cache_in the cache containing query points * @param q_nodes_cache_in the cache containing the query tree * @param r_points_cache_in the cache containing reference points * @param r_nodes_cache_in the cache containing the reference tree * @param q_results_cache_in the cache containing per-query results. */ void Doit(index_t n_threads, int rank, SchedulerInterface *work_queue_in, const typename GNP::Param& param, DistributedCache *q_points_cache_in, DistributedCache *q_nodes_cache_in, DistributedCache *r_points_cache_in, DistributedCache *r_nodes_cache_in, DistributedCache *q_results_cache_in); /** * Gets the GNP's global-result of the entire computation. */ const typename GNP::GlobalResult& global_result() const { return global_result_; } /** * Recursion statistics. */ const DualTreeRecursionStats& stats() const { return stats_; } private: void ThreadBody_(); }; /** * An rpc-style reductor suitable for condensing global results. * * Template parameter GNP is the generalized N-body problem containing * nested classes Param and GlobalResult. */ template class GlobalResultReductor { private: const typename GNP::Param *param_; public: /** Initializes the reductor for a given parameter object. */ void Init(const typename GNP::Param* param_in) { param_ = param_in; } /** * Reduces two elements. * * @param right a new element to merge * @param left the element to merge into */ void Reduce(typename GNP::GlobalResult& right, typename GNP::GlobalResult* left) const { left->Accumulate(*param_, right); } }; /** * Reads points in a data set, just for the master machine. * * This does all the actual reading into the cache but doesn't do any * syncing. It's recommended to just use thor::ReadPoints. * * Template parameters: * @li @c Point - a conformant point type (see gnp.h) * @li @c Param - a parameter object used for initializing points */ template index_t ReadPointsMaster( const Param& param, int points_channel, const char *filename, int block_size_kb, double megs, DistributedCache *points_cache); /** * Reads data points from a file into a data set. * * The Point object must contain the suitable Init and Set method as does * the class ThorVectorPoint in gnp.h. * * This takes in a module, such that the module's root parameter is the * filename. There is optionally another parameter "block_size_kb" which * is the maximum block size in kilobytes, and "megs" which is the minimum * number of megabytes to dedicate to the cache. * * Aborts program on error. * * Template parameters: * @li @c Point - a conformant point type (see gnp.h) * @li @c Param - a parameter object used for initializing points * * @param param the parameter object used for initializing the points * @param points_channel an rpc channel number that can be used for points * @param extra_channel a free channel used for internal purposes * @param module parameters (see above) * @param points_cache an uninitialized cache that will contain the points * * @return the number of points read */ template index_t ReadPoints( const Param& param, int points_channel, int extra_channel, datanode *module, DistributedCache *points_cache); /** * Does a distributed dual-tree computation. * * @param module where to get tuning parameters from and store results in * @param base_channel the begin of a range of 10 free channels * @param param the gnp parameters * @param q the query tree * @param r the reference tree * @param q_results the query results * @param global_result_out (output) if non-NULL, it will be initialized to the * global result on the root machine; on other machines, this will * correspond to a global result of the machine's subtree of processors * (probably not useful to you) */ template void RpcDualTree(datanode *module, int base_channel, const typename GNP::Param& param, QTree *q, RTree *r, DistributedCache *q_results, typename GNP::GlobalResult *global_result_out); /** * A "cookie-cutter" main for monochromatic dual tree problems. * * The @c gnp_name parameter specifies a short name of the problem solved. * If @c gnp_name is @c kde, then for example the @c Param object will * be initialized with the datanode in @c kde, so on the command line you * might type @c kde/bandwidth=1. * * Other parameters: * @li @c n_threads - the number of threads (defaults to 2) * @li @c data - the data file, with sub-parameters explained in * thor::ReadPoints such as @c data/block_size_kb or @c data/megs * @li @c tree - parameters for tree building, such as @c tree/block_size_kb, * @c tree/megs, and @c tree/leaf_size. * * @param module where to read parameters (explained above) * @param gnp_name a short textual name of the GNP */ template void MonochromaticDualTreeMain(datanode *module, const char *gnp_name); }; // end namespace #include "thor_utils_impl.h" #endif