From f687607e15c0a4d7c89713d4e1f9bb93f305db4d Mon Sep 17 00:00:00 2001 From: Giovanni De Toni Date: Mon, 26 Jun 2017 09:17:55 +0200 Subject: [PATCH] [PrematureStopping] Convert CSignal::cancel_computations() to cancel_computation(). Remove CSignal::cancel_computations() and add TODO when the class does not inherit directly from CMachine. --- src/gpl/shogun/lib/external/gpdtsolve.cpp | 4 +- .../malsar/malsar_joint_feature_learning.cpp | 5 +- src/gpl/shogun/lib/slep/slep_mc_plain_lr.cpp | 3 +- src/gpl/shogun/lib/slep/slep_mc_tree_lr.cpp | 3 +- src/gpl/shogun/lib/slep/slep_solver.cpp | 3 +- src/shogun/classifier/AveragedPerceptron.cpp | 2 +- src/shogun/classifier/LPBoost.cpp | 2 +- src/shogun/classifier/Perceptron.cpp | 2 +- src/shogun/classifier/mkl/MKL.cpp | 2 +- src/shogun/classifier/mkl/MKLMulticlass.cpp | 2 +- src/shogun/classifier/svm/LibLinear.cpp | 6 +- src/shogun/classifier/svm/MPDSVM.cpp | 2 +- src/shogun/classifier/svm/NewtonSVM.cpp | 2 +- src/shogun/classifier/svm/OnlineSVMSGD.cpp | 2 +- src/shogun/classifier/svm/SGDQN.cpp | 2 +- src/shogun/classifier/svm/SVMLight.cpp | 6 +- src/shogun/classifier/svm/SVMSGD.cpp | 2 +- src/shogun/classifier/vw/VowpalWabbit.cpp | 2 +- src/shogun/distance/Distance.cpp | 5 +- src/shogun/distributions/HMM.cpp | 4 +- src/shogun/features/DotFeatures.cpp | 22 +++---- .../hashed/HashedWDFeaturesTransposed.cpp | 10 ---- src/shogun/kernel/Kernel.cpp | 5 +- .../WeightedDegreePositionStringKernel.cpp | 46 ++++++++------- .../string/WeightedDegreeStringKernel.cpp | 10 ++-- src/shogun/lib/Signal.h | 9 --- src/shogun/lib/external/shogun_libsvm.cpp | 58 +++++++++++++++++-- src/shogun/machine/KernelMachine.cpp | 12 ++-- src/shogun/multiclass/BruteKNNSolver.cpp | 4 +- src/shogun/multiclass/KDTreeKNNsolver.cpp | 4 +- src/shogun/multiclass/KNN.cpp | 4 +- src/shogun/multiclass/LSHKNNSolver.cpp | 4 +- src/shogun/multiclass/LaRank.cpp | 4 +- .../liblinear/shogun_liblinear.cpp | 4 +- src/shogun/optimization/liblinear/tron.cpp | 4 +- .../transfer/multitask/LibLinearMTL.cpp | 2 +- 36 files changed, 156 insertions(+), 107 deletions(-) diff --git a/src/gpl/shogun/lib/external/gpdtsolve.cpp b/src/gpl/shogun/lib/external/gpdtsolve.cpp index 031670a78e8..234962143c8 100644 --- a/src/gpl/shogun/lib/external/gpdtsolve.cpp +++ b/src/gpl/shogun/lib/external/gpdtsolve.cpp @@ -1311,7 +1311,9 @@ float64_t QPproblem::gpdtsolve(float64_t *solution) } Cache->Iteration(); nit = nit+1; - } while (!optimal() && !(CSignal::cancel_computations())); + // TODO: replace with the new signal + //} while (!optimal() && !(CSignal::cancel_computations())); + } while (!optimal()); /* End of the problem resolution loop */ /***************************************************************************/ diff --git a/src/gpl/shogun/lib/malsar/malsar_joint_feature_learning.cpp b/src/gpl/shogun/lib/malsar/malsar_joint_feature_learning.cpp index dfacec83278..80b5842c9e6 100644 --- a/src/gpl/shogun/lib/malsar/malsar_joint_feature_learning.cpp +++ b/src/gpl/shogun/lib/malsar/malsar_joint_feature_learning.cpp @@ -51,7 +51,10 @@ malsar_result_t malsar_joint_feature_learning( //internal::set_is_malloc_allowed(false); bool done = false; - while (!done && iter <= options.max_iter && !CSignal::cancel_computations()) + // TODO: replace with the new signal + // while (!done && iter <= options.max_iter && + // !CSignal::cancel_computations()) + while (!done && iter <= options.max_iter) { double alpha = double(t_old - 1)/t; diff --git a/src/gpl/shogun/lib/slep/slep_mc_plain_lr.cpp b/src/gpl/shogun/lib/slep/slep_mc_plain_lr.cpp index f10592f2e48..312facdb4ab 100644 --- a/src/gpl/shogun/lib/slep/slep_mc_plain_lr.cpp +++ b/src/gpl/shogun/lib/slep/slep_mc_plain_lr.cpp @@ -91,7 +91,8 @@ slep_result_t slep_mc_plain_lr( bool done = false; CTime time; //internal::set_is_malloc_allowed(false); - while ((!done) && (iterindex_iterator()) diff --git a/src/shogun/classifier/mkl/MKL.cpp b/src/shogun/classifier/mkl/MKL.cpp index 39a58b894a1..bbb96b05cd3 100644 --- a/src/shogun/classifier/mkl/MKL.cpp +++ b/src/shogun/classifier/mkl/MKL.cpp @@ -477,7 +477,7 @@ bool CMKL::train_machine(CFeatures* data) mkl_iterations++; - if (perform_mkl_step(sumw, suma) || CSignal::cancel_computations()) + if (perform_mkl_step(sumw, suma) || cancel_computation()) break; } diff --git a/src/shogun/classifier/mkl/MKLMulticlass.cpp b/src/shogun/classifier/mkl/MKLMulticlass.cpp index 480061f93a2..d3b00c108e5 100644 --- a/src/shogun/classifier/mkl/MKLMulticlass.cpp +++ b/src/shogun/classifier/mkl/MKLMulticlass.cpp @@ -371,7 +371,7 @@ bool CMKLMulticlass::train_machine(CFeatures* data) int32_t numberofsilpiterations=0; bool final=false; - while (!(CSignal::cancel_computations()) && !final) + while (!(cancel_computation()) && !final) { //curweights.clear(); diff --git a/src/shogun/classifier/svm/LibLinear.cpp b/src/shogun/classifier/svm/LibLinear.cpp index 5b45e77c99c..3940dabba75 100644 --- a/src/shogun/classifier/svm/LibLinear.cpp +++ b/src/shogun/classifier/svm/LibLinear.cpp @@ -316,7 +316,7 @@ void CLibLinear::solve_l2r_l1l2_svc( auto pb = progress(range(10)); CTime start_time; - while (iter < max_iterations && !CSignal::cancel_computations()) + while (iter < max_iterations && !cancel_computation()) { if (m_max_train_time > 0 && start_time.cur_time_diff() > m_max_train_time) break; @@ -526,7 +526,7 @@ void CLibLinear::solve_l1r_l2_svc( auto pb = progress(range(10)); CTime start_time; - while (iter < max_iterations && !CSignal::cancel_computations()) + while (iter < max_iterations && !cancel_computation()) { if (m_max_train_time > 0 && start_time.cur_time_diff() > m_max_train_time) break; @@ -898,7 +898,7 @@ void CLibLinear::solve_l1r_lr( auto pb = progress(range(10)); CTime start_time; - while (iter < max_iterations && !CSignal::cancel_computations()) + while (iter < max_iterations && !cancel_computation()) { if (m_max_train_time > 0 && start_time.cur_time_diff() > m_max_train_time) break; diff --git a/src/shogun/classifier/svm/MPDSVM.cpp b/src/shogun/classifier/svm/MPDSVM.cpp index c0de8ac0cb8..89abf942983 100644 --- a/src/shogun/classifier/svm/MPDSVM.cpp +++ b/src/shogun/classifier/svm/MPDSVM.cpp @@ -95,7 +95,7 @@ bool CMPDSVM::train_machine(CFeatures* data) } // go ... - while (niter++ < maxiter && !CSignal::cancel_computations()) + while (niter++ < maxiter && !cancel_computation()) { int32_t maxpidx=-1; float64_t maxpviol = -1; diff --git a/src/shogun/classifier/svm/NewtonSVM.cpp b/src/shogun/classifier/svm/NewtonSVM.cpp index bca0f115512..011aa2ca15c 100644 --- a/src/shogun/classifier/svm/NewtonSVM.cpp +++ b/src/shogun/classifier/svm/NewtonSVM.cpp @@ -82,7 +82,7 @@ bool CNewtonSVM::train_machine(CFeatures* data) float64_t obj, *grad=SG_MALLOC(float64_t, x_d+1); float64_t t; - while(!CSignal::cancel_computations()) + while (!cancel_computation()) { iter++; diff --git a/src/shogun/classifier/svm/OnlineSVMSGD.cpp b/src/shogun/classifier/svm/OnlineSVMSGD.cpp index cdd03b32b7d..0e13405de18 100644 --- a/src/shogun/classifier/svm/OnlineSVMSGD.cpp +++ b/src/shogun/classifier/svm/OnlineSVMSGD.cpp @@ -106,7 +106,7 @@ bool COnlineSVMSGD::train(CFeatures* data) is_log_loss = true; int32_t vec_count; - for(int32_t e=0; estart_parser(); - while (!(CSignal::cancel_computations()) && (env->passes_complete < env->num_passes)) + while (!(cancel_computation()) && (env->passes_complete < env->num_passes)) { while (features->get_next_example()) { diff --git a/src/shogun/distance/Distance.cpp b/src/shogun/distance/Distance.cpp index dc3424ab69d..342936f9130 100644 --- a/src/shogun/distance/Distance.cpp +++ b/src/shogun/distance/Distance.cpp @@ -333,8 +333,9 @@ SGMatrix CDistance::get_distance_matrix() pb.print_progress(); - if (CSignal::cancel_computations()) - break; + // TODO: replace with new signal + // if (CSignal::cancel_computations()) + // break; } } } diff --git a/src/shogun/distributions/HMM.cpp b/src/shogun/distributions/HMM.cpp index 3bc2dd5c556..e5cbec82702 100644 --- a/src/shogun/distributions/HMM.cpp +++ b/src/shogun/distributions/HMM.cpp @@ -5586,7 +5586,9 @@ bool CHMM::baum_welch_viterbi_train(BaumWelchViterbiType type) float64_t prob_train=CMath::ALMOST_NEG_INFTY; iteration_count=iterations; - while (!converged(prob, prob_train) && (!CSignal::cancel_computations())) + // TODO: replace with the new signal + // while (!converged(prob, prob_train) && (!CSignal::cancel_computations())) + while (!converged(prob, prob_train)) { CMath::swap(working, estimate); prob=prob_train; diff --git a/src/shogun/features/DotFeatures.cpp b/src/shogun/features/DotFeatures.cpp index 2ae277cb6c5..c964e911497 100644 --- a/src/shogun/features/DotFeatures.cpp +++ b/src/shogun/features/DotFeatures.cpp @@ -88,8 +88,10 @@ void CDotFeatures::dense_dot_range(float64_t* output, int32_t start, int32_t sto #ifdef WIN32 for (int32_t i=t_start; i CDotFeatures::get_computed_dot_feature_matrix() diff --git a/src/shogun/features/hashed/HashedWDFeaturesTransposed.cpp b/src/shogun/features/hashed/HashedWDFeaturesTransposed.cpp index dfb9a0ae7a0..e4061081243 100644 --- a/src/shogun/features/hashed/HashedWDFeaturesTransposed.cpp +++ b/src/shogun/features/hashed/HashedWDFeaturesTransposed.cpp @@ -291,11 +291,6 @@ void CHashedWDFeaturesTransposed::dense_dot_range(float64_t* output, int32_t sta } #endif SG_FREE(index); - -#ifndef WIN32 - if ( CSignal::cancel_computations() ) - SG_INFO("prematurely stopped. \n") -#endif } void CHashedWDFeaturesTransposed::dense_dot_range_subset(int32_t* sub_index, int num, float64_t* output, float64_t* alphas, float64_t* vec, int32_t dim, float64_t b) @@ -382,11 +377,6 @@ void CHashedWDFeaturesTransposed::dense_dot_range_subset(int32_t* sub_index, int SG_FREE(index); } #endif - -#ifndef WIN32 - if ( CSignal::cancel_computations() ) - SG_INFO("prematurely stopped. \n") -#endif } void* CHashedWDFeaturesTransposed::dense_dot_range_helper(void* p) diff --git a/src/shogun/kernel/Kernel.cpp b/src/shogun/kernel/Kernel.cpp index a1611cb5181..41b4b0baaa0 100644 --- a/src/shogun/kernel/Kernel.cpp +++ b/src/shogun/kernel/Kernel.cpp @@ -1302,8 +1302,9 @@ template void* CKernel::get_kernel_matrix_helper(void* p) pb->print_progress(); - if (CSignal::cancel_computations()) - break; + // TODO: replace with the new signal + // if (CSignal::cancel_computations()) + // break; } } diff --git a/src/shogun/kernel/string/WeightedDegreePositionStringKernel.cpp b/src/shogun/kernel/string/WeightedDegreePositionStringKernel.cpp index 713606b21d2..f5253b81401 100644 --- a/src/shogun/kernel/string/WeightedDegreePositionStringKernel.cpp +++ b/src/shogun/kernel/string/WeightedDegreePositionStringKernel.cpp @@ -1254,26 +1254,28 @@ void CWeightedDegreePositionStringKernel::compute_batch( { auto pb = progress(range(num_feat), *this->io); - for (int32_t j=0; j params; - params.vec=vec; - params.result=result; - params.weights=weights; - params.kernel=this; - params.tries=&tries; - params.factor=factor; - params.j=j; - params.start=0; - params.end=num_vec; - params.length=length; - params.max_shift=max_shift; - params.shift=shift; - params.vec_idx=vec_idx; - compute_batch_helper((void*) ¶ms); - - pb.print_progress(); + // TODO: replace with the new signal + // for (int32_t j=0; j params; + params.vec = vec; + params.result = result; + params.weights = weights; + params.kernel = this; + params.tries = &tries; + params.factor = factor; + params.j = j; + params.start = 0; + params.end = num_vec; + params.length = length; + params.max_shift = max_shift; + params.shift = shift; + params.vec_idx = vec_idx; + compute_batch_helper((void*)¶ms); + + pb.print_progress(); } pb.complete(); } @@ -1282,7 +1284,9 @@ void CWeightedDegreePositionStringKernel::compute_batch( { auto pb = progress(range(num_feat), *this->io); - for (int32_t j=0; j #include #include #include @@ -51,6 +52,8 @@ #include #include +#include + namespace shogun { @@ -290,7 +293,7 @@ LibSVMKernel::~LibSVMKernel() // class Solver { public: - Solver() {}; + Solver() : m_cancel_computation(false){}; virtual ~Solver() {}; struct SolutionInfo { @@ -322,6 +325,7 @@ class Solver { float64_t *G_bar; // gradient, if we treat free variables as 0 int32_t l; bool unshrink; // XXX + std::atomic m_cancel_computation; float64_t get_C(int32_t i) { @@ -343,10 +347,51 @@ class Solver { virtual int32_t select_working_set(int32_t &i, int32_t &j, float64_t &gap); virtual float64_t calculate_rho(); virtual void do_shrinking(); + + /* Custom implementation of signal handling */ + rxcpp::subscription connect_to_signal_handler(); + void reset_computation_variables(); +#ifndef SWIG + /** @return whether the algorithm needs to be stopped */ + SG_FORCED_INLINE bool cancel_computation() const + { + return m_cancel_computation.load(); + } +#endif + void on_pause() + { + } + void on_next() + { + m_cancel_computation.store(false); + } + void on_complete() + { + } + private: bool be_shrunk(int32_t i, float64_t Gmax1, float64_t Gmax2); }; +rxcpp::subscription Solver::connect_to_signal_handler() +{ + // Subscribe this algorithm to the signal handler + auto subscriber = rxcpp::make_subscriber( + [this](int i) { + if (i == SG_PAUSE_COMP) + this->on_pause(); + else + this->on_next(); + }, + [this]() { this->on_complete(); }); + return get_global_signal()->get_observable().subscribe(subscriber); +} + +void Solver::reset_computation_variables() +{ + m_cancel_computation.store(false); +} + void Solver::swap_index(int32_t i, int32_t j) { Q->swap_index(i,j); @@ -403,6 +448,8 @@ void Solver::Solve( const schar *p_y, float64_t *p_alpha, float64_t p_Cp, float64_t p_Cn, float64_t p_eps, SolutionInfo* p_si, int32_t shrinking, bool use_bias) { + auto sub = connect_to_signal_handler(); + this->l = p_l; this->Q = &p_Q; QD=Q->get_QD(); @@ -443,7 +490,7 @@ void Solver::Solve( } SG_SINFO("Computing gradient for initial set of non-zero alphas\n") //CMath::display_vector(alpha, l, "alphas"); - for(i=0;imax_train_time > 0 && start_time.cur_time_diff() > Q->max_train_time) break; @@ -711,6 +758,9 @@ void Solver::Solve( SG_FREE(active_set); SG_FREE(G); SG_FREE(G_bar); + + sub.unsubscribe(); + reset_computation_variables(); } // return 1 if already optimal, return 0 otherwise @@ -1832,7 +1882,7 @@ void solve_c_svc_weighted( if(prob->y[i] > 0) y[i] = +1; else y[i]=-1; } - WeightedSolver s = WeightedSolver(prob->C); + WeightedSolver s{prob->C}; s.Solve(l, SVC_Q(*prob,*param,y), minus_ones, y, alpha, Cp, Cn, param->eps, si, param->shrinking, param->use_bias); diff --git a/src/shogun/machine/KernelMachine.cpp b/src/shogun/machine/KernelMachine.cpp index c6288c32ee0..65f4d0d9178 100644 --- a/src/shogun/machine/KernelMachine.cpp +++ b/src/shogun/machine/KernelMachine.cpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include @@ -364,8 +363,8 @@ SGVector CKernelMachine::apply_get_outputs(CFeatures* data) #ifdef WIN32 for (int32_t vec = start; vec < end; vec++) #else - for (int32_t vec = start; - vec < end && !CSignal::cancel_computations(); vec++) + for (int32_t vec = start; vec < end && !cancel_computation(); + vec++) #endif { pb.print_progress(); @@ -392,7 +391,7 @@ SGVector CKernelMachine::apply_get_outputs(CFeatures* data) } #ifndef WIN32 - if ( CSignal::cancel_computations() ) + if (cancel_computation()) SG_INFO("prematurely stopped. \n") #endif } @@ -523,8 +522,7 @@ SGVector CKernelMachine::apply_locked_get_output( #ifdef WIN32 for (int32_t vec = start; vec < end; vec++) #else - for (int32_t vec = start; vec < end && !CSignal::cancel_computations(); - vec++) + for (int32_t vec = start; vec < end && !cancel_computation(); vec++) #endif { pb.print_progress(); @@ -549,7 +547,7 @@ SGVector CKernelMachine::apply_locked_get_output( } #ifndef WIN32 - if ( CSignal::cancel_computations() ) + if (cancel_computation()) SG_INFO("prematurely stopped.\n") else #endif diff --git a/src/shogun/multiclass/BruteKNNSolver.cpp b/src/shogun/multiclass/BruteKNNSolver.cpp index 8471574fd12..c3538dc6396 100644 --- a/src/shogun/multiclass/BruteKNNSolver.cpp +++ b/src/shogun/multiclass/BruteKNNSolver.cpp @@ -22,7 +22,7 @@ CMulticlassLabels* CBruteKNNSolver::classify_objects(CDistance* knn_distance, co SGMatrix NN = this->nn; //from the indices to the nearest neighbors, compute the class labels - for (index_t i=0; i CBruteKNNSolver::classify_objects_k(CDistance* knn_distance, c //get the k nearest neighbors of each example SGMatrix NN = this->nn; - for (index_t i=0; iget_rhs(); kd_tree->query_knn(dynamic_cast*>(query), m_k); SGMatrix NN = kd_tree->get_knn_indices(); - for (int32_t i=0; i CKDTREEKNNSolver::classify_objects_k(CDistance* knn_distance, CFeatures* data = knn_distance->get_rhs(); kd_tree->query_knn(dynamic_cast*>(data), m_k); SGMatrix NN = kd_tree->get_knn_indices(); - for (index_t i=0; i CKNN::nearest_neighbors() auto pb = progress(range(n), *this->io); //for each test example - for (int32_t i=0; iio); // for each test example - for (int32_t i=0; idata(), sizeof(int32_t)*m_k); delete indices; } - - for (index_t i=0; iio); SG_INFO("Training on %d examples\n", nb_train) - while (gap > get_C() && (!CSignal::cancel_computations()) && - n_it < max_iteration) // stopping criteria + while (gap > get_C() && (!cancel_computation()) && + n_it < max_iteration) // stopping criteria { float64_t tr_err = 0; int32_t ind = step; diff --git a/src/shogun/optimization/liblinear/shogun_liblinear.cpp b/src/shogun/optimization/liblinear/shogun_liblinear.cpp index 1489d84c011..e2a2f748b95 100644 --- a/src/shogun/optimization/liblinear/shogun_liblinear.cpp +++ b/src/shogun/optimization/liblinear/shogun_liblinear.cpp @@ -513,7 +513,9 @@ void Solver_MCSVM_CS::solve() state->inited = true; } - while(iter < max_iter && !CSignal::cancel_computations()) + // TODO: replace with the new signal + // while(iter < max_iter && !CSignal::cancel_computations()) + while (iter < max_iter) { double stopping = -CMath::INFTY; for(i=0;i 0 && start_time.cur_time_diff() > max_train_time) break; diff --git a/src/shogun/transfer/multitask/LibLinearMTL.cpp b/src/shogun/transfer/multitask/LibLinearMTL.cpp index 3a7dabfbf23..6b33a17430d 100644 --- a/src/shogun/transfer/multitask/LibLinearMTL.cpp +++ b/src/shogun/transfer/multitask/LibLinearMTL.cpp @@ -256,7 +256,7 @@ void CLibLinearMTL::solve_l2r_l1l2_svc(const liblinear_problem *prob, double eps auto pb = progress(range(10)); CTime start_time; - while (iter < max_iterations && !CSignal::cancel_computations()) + while (iter < max_iterations && !cancel_computation()) { if (m_max_train_time > 0 && start_time.cur_time_diff() > m_max_train_time) break;