Minuit 2 Memory Leak

Appologies if this has already been reported, I believe I have observed a memory leak when using Minuit2.

I haven’t yet fully figured out where this leak comes from. However the code which I will provide below consumes about 32 GB after 400 iterations.

On another issue, this is a 1 parameter fit, and it is incredibly slow to run. Is there a lot of overhead with the Minuit2 library? I tried moving some of the Minuit2 objects out of the inner loop to reduce the amount of memory allocation/deallocation. It didn’t seem to improve performance. So perhaps my code is slow due to the operator() calculation.

Still, this is currently running, iteration 55, and using 4 GB of ram. I can presumably fix the issue by putting the Minuit2 objects back inside the inner loop, as they seem to free memory correctly on destruction. However I thought someone might want to know this can be an issue and investigate.

Cheers!

    h_mps = new TH2D(mps_name, mps_name,
                           301, -0.1, 1.9,
                           301, 0.95, 1.45);

    h_mps_efficiency = new TH2D(mps_efficiency_name, mps_efficiency_name,
                           301, -0.1, 1.9,
                           301, 0.95, 1.45);

    std::vector<double> params;
    params.push_back(0.0); // A
    params.push_back(0.0); // B
    params.push_back(1.0); // C
    std::vector<double> param_errs;
    param_errs.push_back(0.0); // A
    param_errs.push_back(0.0); // B
    param_errs.push_back(0.1); // C

    // initialization
    ROOT::Minuit2::MnUserParameterState theParameterStatePersistent;
    ROOT::Minuit2::VariableMetricMinimizer theMinimizer;
    MinimizeFCN_FAST theFCN;
    
    ROOT::Minuit2::MnStrategy theStrategy(1); // no clue what it does

    theFCN.h_pointerto_data_p1 = h_data_p1;
    theFCN.h_pointerto_data_p2 = h_data_p2;

    theParameterStatePersistent.Add("C", params.at(2), param_errs.at(2));

    std::chrono::system_clock::time_point master_start_time = std::chrono::high_resolution_clock::now();

    for(Int_t i = 1; i <= h_mps->GetNbinsX(); ++ i)
    {
        std::cout << "i=" << i << "/" << h_mps->GetNbinsX() << std::endl;

        for(Int_t j = 1; j <= h_mps->GetNbinsY(); ++ j)
        {
            
            double A0 = 0.0;
            double A2 = 0.0;

            {
                const double xi_31 = h_mps->GetXaxis()->GetBinCenter(i);
                const double A = h_mps->GetYaxis()->GetBinCenter(j);

                convert_ps_coeff_forward(A, xi_31, A0, A2);
            }


            ///////////////////////////////////////////////////////////////////
            // calculate chi2
            ///////////////////////////////////////////////////////////////////

            params.at(0) = A0;
            params.at(1) = A2;
            params.at(2) = 1.0;
            param_errs.at(0) = 0.0;
            param_errs.at(1) = 0.0;
            param_errs.at(2) = 0.1;

            double chi2_p1, chi2_p2;

            ///////////////////////////////////////////////////////////////////
            // perform fit
            ///////////////////////////////////////////////////////////////////

            SYS_COVMATRIX_ENABLE_MINUIT = true;
            SYS_COVMATRIX_ENABLE_CALC = true;

            // initialize
            theFCN.A_G0 = params.at(0);
            theFCN.A_G2 = params.at(1);

            theParameterStatePersistent.SetValue(0, params.at(2));
            theParameterStatePersistent.SetError(0, param_errs.at(2));

            // exec
            ROOT::Minuit2::FunctionMinimum FCN_min =
                theMinimizer.Minimize(theFCN, theParameterStatePersistent, theStrategy);

            double eff = FCN_min.UserParameters().Params().at(0);
            double chi2 = FCN_min.Fval();

            h_mps->SetBinContent(i, j, chi2);
            h_mps_efficiency->SetBinContent(i, j, eff);

        } // h_mps j


        std::chrono::system_clock::time_point outloop_end_time = std::chrono::high_resolution_clock::now();

        std::chrono::duration<double> total_runtime_sec = outloop_end_time - master_start_time;
        int number_of_runs_completed = i + 1;
        int number_of_runs_remaining = 301 - (i + 1);
        double remaining_runtime_sec = total_runtime_sec.count() / (double)number_of_runs_completed * (double)(number_of_runs_remaining);
        double remaining_runtime_hr = remaining_runtime_sec / 3600.0;
        std::cout << "ETA: " << remaining_runtime_hr << " h" << std::endl;


    } // h_mps i

ROOT Version:

ROOT Version: 6.18/04
Built for linuxx8664gcc on Sep 11 2019, 15:38:23
From tags/v6-18-04@v6-18-04

Platform: Linux x86_64
Compiler: gcc


My applogies, I think I have tracked the issue down to my own code, where I allocate TMatrix objects.

I am guessing these are not managed internally by ROOT memory manager. If so, this is the source of the memory leak. Nothing to do with Minuit2.

1 Like

Just to confirm - it seems that ROOT does not manage the memory of TMatrix objects automatically. This was the cause of the issue. (In case anyone was wondering.)

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.