From f0888468e63a2a0c20f4c15f03aa6b388ff932f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Villemot?= <sebastien@dynare.org> Date: Fri, 31 Mar 2023 18:44:24 +0200 Subject: [PATCH] Bytecode: optimize memory consumption during iterations mxArray objects were not properly destroyed within the iteration loop, leading to higher memory usage. Note that there was no memory leak, because these objects would be destroyed later by MATLAB when exiting the MEX. --- mex/sources/bytecode/SparseMatrix.cc | 52 +++++++++++++++++----------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/mex/sources/bytecode/SparseMatrix.cc b/mex/sources/bytecode/SparseMatrix.cc index bb4bd78051..62bba0dd05 100644 --- a/mex/sources/bytecode/SparseMatrix.cc +++ b/mex/sources/bytecode/SparseMatrix.cc @@ -2592,6 +2592,7 @@ dynSparseMatrix::Solve_Matlab_GMRES(mxArray *A_m, mxArray *b_m, int Size, double } mxDestroyArray(A_m); mxDestroyArray(b_m); + mxDestroyArray(x0_m); mxDestroyArray(z); mxDestroyArray(flag); } @@ -2751,6 +2752,7 @@ dynSparseMatrix::Solve_Matlab_BiCGStab(mxArray *A_m, mxArray *b_m, int Size, dou } mxDestroyArray(A_m); mxDestroyArray(b_m); + mxDestroyArray(x0_m); mxDestroyArray(z); } @@ -3784,12 +3786,6 @@ dynSparseMatrix::Simulate_One_Boundary(int block_num, int y_size, int size) Simple_Init(size, IM_i, zero_solution); else { - b_m = mxCreateDoubleMatrix(size, 1, mxREAL); - if (!b_m) - throw FatalException{"In Simulate_One_Boundary, can't allocate b_m vector"}; - A_m = mxCreateSparse(size, size, min(static_cast<int>(IM_i.size()*2), size * size), mxREAL); - if (!A_m) - throw FatalException{"In Simulate_One_Boundary, can't allocate A_m matrix"}; x0_m = mxCreateDoubleMatrix(size, 1, mxREAL); if (!x0_m) throw FatalException{"In Simulate_One_Boundary, can't allocate x0_m vector"}; @@ -3797,6 +3793,12 @@ dynSparseMatrix::Simulate_One_Boundary(int block_num, int y_size, int size) || ((stack_solve_algo == 0 || stack_solve_algo == 1 || stack_solve_algo == 4 || stack_solve_algo == 6) && !steady_state))) { + b_m = mxCreateDoubleMatrix(size, 1, mxREAL); + if (!b_m) + throw FatalException{"In Simulate_One_Boundary, can't allocate b_m vector"}; + A_m = mxCreateSparse(size, size, min(static_cast<int>(IM_i.size()*2), size * size), mxREAL); + if (!A_m) + throw FatalException{"In Simulate_One_Boundary, can't allocate A_m matrix"}; Init_Matlab_Sparse_Simple(size, IM_i, A_m, b_m, zero_solution, x0_m); A_m_save = mxDuplicateArray(A_m); b_m_save = mxDuplicateArray(b_m); @@ -3836,7 +3838,10 @@ dynSparseMatrix::Simulate_One_Boundary(int block_num, int y_size, int size) else if ((solve_algo == 8 && steady_state) || (stack_solve_algo == 3 && !steady_state)) Solve_Matlab_BiCGStab(A_m, b_m, size, slowc, block_num, false, it_, x0_m, preconditioner); else if ((solve_algo == 6 && steady_state) || ((stack_solve_algo == 0 || stack_solve_algo == 1 || stack_solve_algo == 4 || stack_solve_algo == 6) && !steady_state)) - Solve_LU_UMFPack(Ap, Ai, Ax, b, size, size, slowc, false, it_); + { + Solve_LU_UMFPack(Ap, Ai, Ax, b, size, size, slowc, false, it_); + mxDestroyArray(x0_m); + } } return singular_system; } @@ -4154,28 +4159,35 @@ dynSparseMatrix::Simulate_Newton_Two_Boundaries(int blck, int y_size, int y_kmin Init_GE(periods, y_kmin, y_kmax, Size, IM_i); else { - b_m = mxCreateDoubleMatrix(periods*Size, 1, mxREAL); - if (!b_m) - throw FatalException{"In Simulate_Newton_Two_Boundaries, can't allocate b_m vector"}; x0_m = mxCreateDoubleMatrix(periods*Size, 1, mxREAL); if (!x0_m) throw FatalException{"In Simulate_Newton_Two_Boundaries, can't allocate x0_m vector"}; - if (stack_solve_algo != 0 && stack_solve_algo != 4) - { - A_m = mxCreateSparse(periods*Size, periods*Size, IM_i.size()* periods*2, mxREAL); - if (!A_m) - throw FatalException{"In Simulate_Newton_Two_Boundaries, can't allocate A_m matrix"}; - } if (stack_solve_algo == 0 || stack_solve_algo == 4) Init_UMFPACK_Sparse(periods, y_kmin, y_kmax, Size, IM_i, &Ap, &Ai, &Ax, &b, x0_m, vector_table_conditional_local, blck); else - Init_Matlab_Sparse(periods, y_kmin, y_kmax, Size, IM_i, A_m, b_m, x0_m); - + { + b_m = mxCreateDoubleMatrix(periods*Size, 1, mxREAL); + if (!b_m) + throw FatalException{"In Simulate_Newton_Two_Boundaries, can't allocate b_m vector"}; + if (stack_solve_algo != 0 && stack_solve_algo != 4) + { + A_m = mxCreateSparse(periods*Size, periods*Size, IM_i.size()* periods*2, mxREAL); + if (!A_m) + throw FatalException{"In Simulate_Newton_Two_Boundaries, can't allocate A_m matrix"}; + } + Init_Matlab_Sparse(periods, y_kmin, y_kmax, Size, IM_i, A_m, b_m, x0_m); + } } if (stack_solve_algo == 0 || stack_solve_algo == 4) - Solve_LU_UMFPack(Ap, Ai, Ax, b, Size * periods, Size, slowc, true, 0, vector_table_conditional_local); + { + Solve_LU_UMFPack(Ap, Ai, Ax, b, Size * periods, Size, slowc, true, 0, vector_table_conditional_local); + mxDestroyArray(x0_m); + } else if (stack_solve_algo == 1 || stack_solve_algo == 6) - Solve_Matlab_Relaxation(A_m, b_m, Size, slowc); + { + Solve_Matlab_Relaxation(A_m, b_m, Size, slowc); + mxDestroyArray(x0_m); + } else if (stack_solve_algo == 2) Solve_Matlab_GMRES(A_m, b_m, Size, slowc, blck, true, 0, x0_m); else if (stack_solve_algo == 3) -- GitLab