#ifndef LIGHTGBM_TREELEARNER_PARALLEL_TREE_LEARNER_H_ #define LIGHTGBM_TREELEARNER_PARALLEL_TREE_LEARNER_H_ #include #include #include "serial_tree_learner.h" #include #include #include namespace LightGBM { /*! * \brief Feature parallel learning algorithm. * Different machine will find best split on different features, then sync global best split * It is recommonded used when #data is small or #feature is large */ class FeatureParallelTreeLearner: public SerialTreeLearner { public: explicit FeatureParallelTreeLearner(const TreeConfig* tree_config); ~FeatureParallelTreeLearner(); void Init(const Dataset* train_data) override; protected: void BeforeTrain() override; void FindBestSplitsForLeaves() override; private: /*! \brief rank of local machine */ int rank_; /*! \brief Number of machines of this parallel task */ int num_machines_; /*! \brief Buffer for network send */ std::vector input_buffer_; /*! \brief Buffer for network receive */ std::vector output_buffer_; }; /*! * \brief Data parallel learning algorithm. * Workers use local data to construct histograms locally, then sync up global histograms. * It is recommonded used when #data is large or #feature is small */ class DataParallelTreeLearner: public SerialTreeLearner { public: explicit DataParallelTreeLearner(const TreeConfig* tree_config); ~DataParallelTreeLearner(); void Init(const Dataset* train_data) override; void ResetConfig(const TreeConfig* tree_config) override; protected: void BeforeTrain() override; void FindBestThresholds() override; void FindBestSplitsForLeaves() override; void Split(Tree* tree, int best_Leaf, int* left_leaf, int* right_leaf) override; inline data_size_t GetGlobalDataCountInLeaf(int leaf_idx) const override { if (leaf_idx >= 0) { return global_data_count_in_leaf_[leaf_idx]; } else { return 0; } } private: /*! \brief Rank of local machine */ int rank_; /*! \brief Number of machines of this parallel task */ int num_machines_; /*! \brief Buffer for network send */ std::vector input_buffer_; /*! \brief Buffer for network receive */ std::vector output_buffer_; /*! \brief different machines will aggregate histograms for different features, use this to mark local aggregate features*/ std::vector is_feature_aggregated_; /*! \brief Block start index for reduce scatter */ std::vector block_start_; /*! \brief Block size for reduce scatter */ std::vector block_len_; /*! \brief Write positions for feature histograms */ std::vector buffer_write_start_pos_; /*! \brief Read positions for local feature histograms */ std::vector buffer_read_start_pos_; /*! \brief Size for reduce scatter */ int reduce_scatter_size_; /*! \brief Store global number of data in leaves */ std::vector global_data_count_in_leaf_; }; /*! * \brief Voting based data parallel learning algorithm. * Like data parallel, but not aggregate histograms for all features. * Here using voting to reduce features, and only aggregate histograms for selected features. * When #data is large and #feature is large, you can use this to have better speed-up */ class VotingParallelTreeLearner: public SerialTreeLearner { public: explicit VotingParallelTreeLearner(const TreeConfig* tree_config); ~VotingParallelTreeLearner() { } void Init(const Dataset* train_data) override; void ResetConfig(const TreeConfig* tree_config) override; protected: void BeforeTrain() override; bool BeforeFindBestSplit(const Tree* tree, int left_leaf, int right_leaf) override; void FindBestThresholds() override; void FindBestSplitsForLeaves() override; void Split(Tree* tree, int best_Leaf, int* left_leaf, int* right_leaf) override; inline data_size_t GetGlobalDataCountInLeaf(int leaf_idx) const override { if (leaf_idx >= 0) { return global_data_count_in_leaf_[leaf_idx]; } else { return 0; } } /*! * \brief Perform global voting * \param leaf_idx index of leaf * \param splits All splits from local voting * \param out Result of gobal voting, only store feature indices */ void GlobalVoting(int leaf_idx, const std::vector& splits, std::vector* out); /*! * \brief Copy local histgram to buffer * \param smaller_top_features Selected features for smaller leaf * \param larger_top_features Selected features for larger leaf */ void CopyLocalHistogram(const std::vector& smaller_top_features, const std::vector& larger_top_features); private: /*! \brief Tree config used in local mode */ TreeConfig local_tree_config_; /*! \brief Voting size */ int top_k_; /*! \brief Rank of local machine*/ int rank_; /*! \brief Number of machines */ int num_machines_; /*! \brief Buffer for network send */ std::vector input_buffer_; /*! \brief Buffer for network receive */ std::vector output_buffer_; /*! \brief different machines will aggregate histograms for different features, use this to mark local aggregate features*/ std::vector smaller_is_feature_aggregated_; /*! \brief different machines will aggregate histograms for different features, use this to mark local aggregate features*/ std::vector larger_is_feature_aggregated_; /*! \brief Block start index for reduce scatter */ std::vector block_start_; /*! \brief Block size for reduce scatter */ std::vector block_len_; /*! \brief Read positions for feature histgrams at smaller leaf */ std::vector smaller_buffer_read_start_pos_; /*! \brief Read positions for feature histgrams at larger leaf */ std::vector larger_buffer_read_start_pos_; /*! \brief Size for reduce scatter */ int reduce_scatter_size_; /*! \brief Store global number of data in leaves */ std::vector global_data_count_in_leaf_; /*! \brief Store global split information for smaller leaf */ std::unique_ptr smaller_leaf_splits_global_; /*! \brief Store global split information for larger leaf */ std::unique_ptr larger_leaf_splits_global_; /*! \brief Store global histogram for smaller leaf */ std::unique_ptr smaller_leaf_histogram_array_global_; /*! \brief Store global histogram for larger leaf */ std::unique_ptr larger_leaf_histogram_array_global_; std::vector smaller_leaf_histogram_data_; std::vector larger_leaf_histogram_data_; std::vector feature_metas_; }; } // namespace LightGBM #endif // LightGBM_TREELEARNER_PARALLEL_TREE_LEARNER_H_