Added script to empirically profile memory usage and time for execution.

This commit is contained in:
Karthik 2025-04-30 12:32:16 +02:00
parent 055ca7ddc9
commit f9bc6d032c
3 changed files with 71 additions and 11 deletions

View File

@ -0,0 +1,57 @@
function [varargout] = runWithProfiling(funcHandle, nOutputs, saveDirectory)
%RUNWITHPROFILING Profile runtime and memory usage, and log stats to JSON file.
%
% Usage:
% [a, b, c, stats] = runWithProfiling(@() sim.run(), 3, './Results/');
%
% Inputs:
% funcHandle - Function handle to run (e.g., @() sim.run())
% nOutputs - Number of outputs expected from funcHandle
% saveDirectory - Directory path to save stats JSON file
%
% Outputs:
% varargout - Outputs of funcHandle (1 to nOutputs)
% - Final output is a struct 'stats' with fields:
% .runtime - Wall-clock time (s)
% .workspaceMemoryMB - Total memory used (MB)
% .timestamp - ISO timestamp of run
% .hostname - System hostname
% Time the function
tStart = tic;
[varargout{1:nOutputs}] = funcHandle();
runtime = toc(tStart);
% Estimate workspace memory usage
try
vars = whos;
totalBytes = sum([vars.bytes]);
workspaceMemoryMB = totalBytes / 1e6;
catch
workspaceMemoryMB = NaN;
end
% Create stats struct
stats.runtime = runtime;
stats.workspaceMemoryMB = workspaceMemoryMB;
stats.timestamp = datestr(now, 'yyyy-mm-dd_HH-MM-SS');
[~, hostname] = system('hostname');
stats.hostname = strtrim(hostname);
% Save as JSON
try
if ~exist(saveDirectory, 'dir')
mkdir(saveDirectory);
end
filename = fullfile(saveDirectory, ['profiling_stats_', stats.timestamp, '.json']);
jsonStr = jsonencode(stats, 'PrettyPrint', true);
fid = fopen(filename, 'w');
fwrite(fid, jsonStr, 'char');
fclose(fid);
catch ME
warning('Failed to save profiling stats: %s', ME.message);
end
% Return stats
varargout{nOutputs + 1} = stats;
end

View File

@ -3,7 +3,7 @@
% Important: Run only sectionwise!!
%% - Create Simulator, Potential and Calculator object with specified options
% - Imaginary-Time
OptionsStruct = struct;
OptionsStruct.NumberOfAtoms = 40000;
@ -21,9 +21,9 @@ OptionsStruct.IncludeDDICutOff = true;
OptionsStruct.CutoffType = 'Cylindrical';
OptionsStruct.SimulationMode = 'EnergyMinimization'; % 'ImaginaryTimeEvolution' | 'RealTimeEvolution' | 'EnergyMinimization'
OptionsStruct.GradientDescentMethod = 'HeavyBall'; % 'HeavyBall' | 'NonLinearCGD'
OptionsStruct.MaxIterationsForGD = 2E5;
OptionsStruct.TimeStepSize = 1E-4; % in s
OptionsStruct.MinimumTimeStepSize = 2E-10; % in s
OptionsStruct.MaxIterationsForGD = 1000;
OptionsStruct.TimeStepSize = 1E-3; % in s
OptionsStruct.MinimumTimeStepSize = 1E-6; % in s
OptionsStruct.TimeCutOff = 2E6; % in s
OptionsStruct.EnergyTolerance = 5E-10;
OptionsStruct.ResidualTolerance = 1E-08;
@ -33,16 +33,18 @@ OptionsStruct.PlotLive = true;
OptionsStruct.JobNumber = 0;
OptionsStruct.RunOnGPU = false;
OptionsStruct.SaveData = true;
OptionsStruct.SaveDirectory = './Results/Data_3D/GradientDescent';
OptionsStruct.SaveDirectory = './Results/Data_3D/GradientDescent'; % './Results/Data_3D/AnisotropicTrap/Tilted0'
options = Helper.convertstruct2cell(OptionsStruct);
clear OptionsStruct
sim = Simulator.DipolarGas(options{:});
pot = Simulator.Potentials(options{:});
sim.Potential = pot.trap(); % + pot.repulsive_chopstick();
%-% Run Simulation %-%
[Params, Transf, psi, V, VDk] = sim.run();
NumberOfOutputs = 5;
[Params, Transf, psi, V, VDk, stats] = Helper.runWithProfiling(@() sim.run(), NumberOfOutputs, OptionsStruct.SaveDirectory);
fprintf('Runtime: %.3f seconds\n', stats.runtime);
fprintf('Memory used: %.2f MB\n', stats.workspaceMemoryMB);
%% - Plot numerical grid
% Plotter.visualizeSpace(Transf)

View File

@ -5,8 +5,9 @@
# Request number of nodes and GPU for job
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --gres=gpu:A40:1
#SBATCH --mem=2G
#SBATCH --cpus-per-task=4
#SBATCH --gres=gpu:1
#SBATCH --mem=12G
# Estimated wallclock time for job
#SBATCH --time=03:00:00
#SBATCH --job-name=simulation