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