Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matlab - seemingly simple instruction causes high cpu load

Tags:

matlab

I am writing a Matlab script that implements a noisegate algorithm. It iterates over the length of an input signal (which I created in the same script) and processes sample by sample. The algorithm itself doesn't require much memory (it carries over two values to the next iteration, namely x_peak_old and g_old). However, to monitor the internal process of the algorithm, I created some additional debug vectors that are the same length of the input signal and get updated with each loop. I comment them in and out as needed.

However, my problem is that one of these vectors behaves strangely. If I disable this vector and hit 'Run', the script executes and finishes in an instant. However, when I assign values to this specific vector each loop and run the script, it takes several seconds to compute and one core of my CPU is at 100% load during this time.

Here's the code:

clear all; close all;

% ***** Parameter *****
Fs = 44100; % Samplerate
ta = 5; % Attack time in ms
tr = 300; % Release time in ms
th = -8; % Threshold in dB
R = 0.05; % Ratio in dB/dB

% ***** Test signal *****
f0 = 20000; % Frequency in Hz
a = (0:Fs) ./ Fs;
aflip = fliplr(a);
sine = sin((2 * pi * f0 / Fs) .* (0:Fs));
sinedecay = zeros(1, Fs);
for k = 1:(Fs+1)
    sinedecay(k) = sine(k)*aflip(k);
end
zeropad = zeros(1, Fs);
% Sine only
% x = [zeropad sine sinedecay zeropad];
% Triangle Rectangle Sine
x = [zeropad a (1-a) -a a-1 zeropad ones(1, Fs) (-1).*ones(1,Fs) zeropad sine sine sinedecay zeropad];
% Dirac
%x = [zeropad 1 zeropad];
siglen = length(x);
x_axis = (1:siglen) ./ Fs;

% ***** Output signal *****
y = zeros(1, siglen);

% ***** Debug signals *****
%threshold = 10^(th/20) .* ones(1, siglen);
%xpeakt = zeros(1, siglen);
%peaklogt = zeros(1, siglen);
%ctrl_logt = zeros(1, siglen);
f_t = zeros(1, siglen);
gt = zeros(1, siglen);

% ***** Derived parameters *****

AT = 1/(1+ta*Fs/1000);
RT = 1-1/(1+tr*Fs/1000);
TH_log = log2( 10^(th/20));
S = 1 - 1/R;

% ***** Initial parameters *****

x_peak_old = 0;
g_old = 0;

% ***** Lets go! *****

for i = 1:siglen 

% Peak measurement
    p0 = abs(x(i));
    x_peak = x_peak_old * RT;
    if (p0 > x_peak)
        x_peak = p0 * AT + x_peak_old *(1-AT);
    end
    x_peak_old = x_peak;
%    xpeakt(i) = x_peak; % DEBUG
    x_peak_log = log2(x_peak);
%    peaklogt(i) = x_peak_log; % DEBUG

% Compare with threshold

    ctrl_log = TH_log - x_peak_log;
    if (ctrl_log < 0)
        ctrl_log = 0;
    end
%    ctrl_logt(i) = ctrl_log; %DEBUG

% Calculation of weight factor

    f = S * ctrl_log;
    f_t(i) = f; %DEBUG
    g = 2^f;

% Smoothing filter for weight factor
    if (g > g_old) 
        coeff = 1-AT;
    else
        coeff = 1-RT;
    end
    temp = g;    
    g = coeff * g + (1-coeff) * g_old;
    g_old = temp;

    % THE FOLLOWING LINE CAUSES PROBLEMS
    gt(i) = g; % DEBUG

% Calculation output signal
    y(i) = x(i) * g;
end

% ***** Plot input, output and debug signals *****
figure;
subplot(211);
plot(x_axis, x);
hold on; grid on;
%plot(x_axis, threshold);
%plot(x_axis, xpeakt); %DEBUG
%plot(x_axis, peaklogt); %DEBUG
%plot(x_axis, ctrl_logt); %DEBUG
plot(x_axis, f_t); %DEBUG
%plot(x_axis, gt); %DEBUG
subplot(212);
plot(x_axis, y);

The line that is causing the issues is the one near the end:

gt(i) = g; % DEBUG

However, just a few lines before, in the same loop, I assing a value to a vector the same way:

f_t(i) = f; %DEBUG

Both vectors are initialized the same way. There are more vectors in this loop that are treated the exact same way, but it is only the gt(i) vector that behaves odd.

I tested this script on two different machines running Matlab R2014b. What is causing this issue?

like image 1000
UnbescholtenerBuerger Avatar asked Mar 10 '23 16:03

UnbescholtenerBuerger


1 Answers

Just change the name of your variable gt to something else (other than the name of a built-in function).


I think this is exactly the case The Mathworks warn you about when they tell you that it is not recommended to overload built-in function.

The gt function is the full form of the shorthand operator >.

Before running the script:

>> which gt
built-in (C:\TLAB13a\toolbox\matlab\ops\@double\gt)  % double method

And after running your script:

>> which gt
gt is a variable.

I can reproduce the described behaviour in Matlab R2013a (~7.5s with the debug variable, 0.1s without).

Note that on R2016a this behaviour is inexistant (~0.12s for both versions). The newer Matlab engine are not so easily confused by overloaded built in functions.


In your case, and for people using older Matlab version, just changing the variable name from gt to anything else (other than the name of another built-in function), gtx for example, make the script run fine and fast even with the debug variables.

like image 132
Hoki Avatar answered Apr 01 '23 16:04

Hoki