Tuesday, October 12, 2010

Timing Loops in MATLAB

This probably wouldn't work as the symbol of a church, more than anything because it would be a pain in the ass to hew from a block of wood.

More than Windows vs. Linux, Macs vs. PCs, or Stanford vs. Cal, engineers who simulate with Matlab versus those who use a real programming language (C,C++) have arguments over their respective merits with religious zeal. I try to straddle both camps; unfortunately most of the time I feel like a jack of all trades, master of none. For some of the systems I try to simulate, namely PLLs and ΔΣ modulators, the competing timescales of the slow-er baseband dynamics versus the high speed oscillator/modulator requires very optimized code to get any reasonable speed. Now there are lots of tricks to play to accelerate things, but the point is if you need raw speed Matlab is not the way to go. On the other hand, if you aren't sure how to build your system up and you just want to play around a bit, Matlab has a much more friendly environment to construct incrementally rather than planning everything first. Programming with Matlab is sort of like driving an automatic car; the car takes care of the shifting for you, and all you have to do is press "go" or "stop" with your foot. With Matlab you can define and re-define variables all you want and call any number of the million inbuilt scripts, but you give up a bit of performance and control over the implementation of functions and allocation of memory.

Anyway, if you ever get stuck running a dumb for loop in Matlab, and want to know if you have enough time to get a beer before it finishes, you can try this code. It uses tic to estimate time to completion by measuring how long it took to do a certain number of iterations, and then divides that by how many more iterations there are left to go.

if (mod(ITER_VAR,NUM_ITER) == 0)
    clc;
    tmp = toc;
    tic;
    tmp = tmp*(TOTAL_ITER-ITER_VAR)/NUM_ITER;
    h_rem = floor(tmp/3600);
    m_rem = floor( (tmp - 3600*h_rem)/60);
    s_rem = round(tmp - 3600*h_rem - 60*m_rem);
    h_rem = num2str(h_rem);
    if (m_rem < 10)
        m_rem = strcat('0',num2str(m_rem));
    else
        m_rem = num2str(m_rem);
    end
    if (s_rem < 10)
        s_rem = strcat('0',num2str(s_rem));
    else
        s_rem = num2str(s_rem);
    end
    Time_Remaining = strcat(h_rem,':',m_rem,':',s_rem)
end


The looping variable is ITER_VAR. The number NUM_ITER should be about the number of iterations your loop does per second, so that the countdown refreshes once per second. If you make it update faster, it will appear more real-time, but it adds execution overhead. Adjust to taste. the number TOTAL_ITER is the final value of ITER_VAR, and is used to estimate how much time is remaining in the simulation.