Show CPU cores utilization in MATLAB

2020-07-10 12:20发布

问题:

Is anyway (any function etc) to show CPU cores utilization in MATLAB in a GUI likes that we have in Task Manager of windows (Performance Tab)?

Thanks.

回答1:

To my knowledge, there are no Matlab function which can access the system properties at the level of the process usage. To get this information one must call external classes.

A search on internet can fetch you some Java classes which can query the process properties. The advantage of the Java approach is it is more likely to be cross-platform.

For windows user, there are still 2 ways of querying these information: by direct call to windows API (faster, but quite complicated to put in place in Matlab), and by using .net object (slower, but uber easy as Matlab handle .net classes almost seamlessly).


  • Create the object

We need to tell Matlab to instantiate a System.Diagnostics.PerformanceCounter object. For the example /i create two of these objects, one which looks at the System Idle Process (called Idle) and one which looks at the Matlab process (this one will report Matlab CPU usage).

function mon = createMonitor
   MatlabProcess = System.Diagnostics.Process.GetCurrentProcess(); % "Matlab" process
   cpuIdleProcess = 'Idle' ;
   mon.NumOfCPU = double(System.Environment.ProcessorCount);
   mon.ProcPerfCounter.Matlab  = System.Diagnostics.PerformanceCounter('Process', '% Processor Time', MatlabProcess.ProcessName );
   mon.ProcPerfCounter.cpuIdle = System.Diagnostics.PerformanceCounter('Process', '% Processor Time', cpuIdleProcess );
end

  • Querying the object

With windows API we'd have to do a lot of machine cycle calculations ourselves, but these .net object are neat because they do all that for you (at a cost of performance though). So now it is only a matter of calling the object and asking what was the last CPU usage ... easy.

The only detail to care for, is that the number reported is only for the processor core which was in use by the process, so if you have multiple core, the reported number has to be divided by the total number of processor to get an overall figure.

   % Calculate the cpu usage
   cpu.total = 100 - h.mon.ProcPerfCounter.cpuIdle.NextValue / h.mon.NumOfCPU ;
   cpu.matlab = h.mon.ProcPerfCounter.Matlab.NextValue / h.mon.NumOfCPU ;

  • Displaying

There you go. The most difficult part was to know and access these .net subtleties. Now if you want a true monitor, you'll need to define a timer which will call these methods at regular interval, then display the results.

Just be aware that calling these .net objects is quite expensive in processor time, so if you create too many PerformanceCounter your monitor will end up eating most of the processor time (one for each process would be quite taxing for example) ... and don't try to refresh your timer at crazy short intervals either


  • Fully functional example:

Sorry but 90% of it is just for the gui mechanics (which I kept as rough as possible but still) so i won't explain all of it. The only important bits were the snippets shown above (which are included in the fully functional example below).

function hcol = CPU_monitor

h = create_gui ;

end

function mon = createMonitor
   MatlabProcess = System.Diagnostics.Process.GetCurrentProcess(); %// "Matlab" process
   cpuIdleProcess = 'Idle' ;
   mon.NumOfCPU = double(System.Environment.ProcessorCount);
   mon.ProcPerfCounter.Matlab  = System.Diagnostics.PerformanceCounter('Process', '% Processor Time', MatlabProcess.ProcessName );
   mon.ProcPerfCounter.cpuIdle = System.Diagnostics.PerformanceCounter('Process', '% Processor Time', cpuIdleProcess );
end

function updateMeasure(obj,evt,hfig)
   h = guidata(hfig) ;
   %// Calculate the cpu usage
   cpu.total = 100 - h.mon.ProcPerfCounter.cpuIdle.NextValue / h.mon.NumOfCPU ;
   cpu.matlab = h.mon.ProcPerfCounter.Matlab.NextValue / h.mon.NumOfCPU ;
   %// update the display
   set(h.txtTotalCPU,'String',num2str(cpu.total,'%5.2f %%') )
   set(h.txtMatlabCPU,'String',num2str(cpu.matlab,'%5.2f %%') )
end

function StartMonitor(obj,evt)
   h = guidata(obj) ;
   start(h.t)
end
function StopMonitor(obj,evt)
   h = guidata(obj) ;
   stop(h.t)
end

function h = create_gui %// The boring part

   h.fig = figure('Unit','Pixels','Position',[200 800 240 120],'MenuBar','none','Name','CPU usage %','NumberTitle','off') ;

   h.btnStart = uicontrol('Callback',@StartMonitor,'Position',[10 80 100 30],'String', 'START' );
   h.btnStart = uicontrol('Callback',@StopMonitor,'Position',[130 80 100 30 ],'String', 'STOP' );

   h.lbl1 = uicontrol('HorizontalAlignment','right','Position',[10 50 100 20],'String','TOTAL :','Style','text' );
   h.txtTotalCPU = uicontrol('Position',[130 50 100 20],'String','0','Style','text' ) ;

   h.lbl2 = uicontrol('HorizontalAlignment','right','Position',[10 10 100 20],'String','Matlab :','Style','text' );
   h.txtMatlabCPU = uicontrol('Position',[130 10 100 20],'String','0','Style','text' ) ;

   movegui(h.fig,'center')

   %// create the monitor
   h.mon = createMonitor ;

   %// Create the timer
   h.t = timer;
   h.t.Period = 1;
   h.t.ExecutionMode = 'fixedRate';
   h.t.TimerFcn = {@updateMeasure,h.fig} ;
   h.t.TasksToExecute = Inf;

   %// store the handle collection
   guidata(h.fig,h)

end