Efficient and quick way to summation of large data points
3 views (last 30 days)
Show older comments
I have a large data points of about 1e7 (voltage with respect to time) of which I need to measure allan deviation. I averaged out and skipped the datapoints 2e5. I used about 90 discrete values of averaging time (tau) using the log space. The code is given below. Yet it take 14 minutes to run the program. Is there anything that I could do to reduce the running time?
Kindly suggest any improvement in the program. Thanks in advance.
% Data Pre-processing (DC Zero level in window of 33 data points)
% Data Pre-processing (Skip data points - first data point in each window of 33)
V = floor(length(voltage)/33);
c = zeros(1, V);
t = zeros(1, V);
d = zeros(1, V);
l=1;
for i=1:33:33*V
k=0;
for j=1:1+32
k=k+voltage(j);
end
k=k/33;
for j=i:i+32
c(j)=voltage(j)-k;
end
t(l)=time(i);
d(l)=c(i);
l=l+1;
end
t = transpose(t);
d = transpose(d);
% Voltage (V) to Omega (deg/hr)
% Omega = Voltage / Sensitivity, where Sensitivity is 9.27 mV/deg/s
omega = (d/9.27e-3)*3600;
N = length(omega);
% Setting Averaging time
t0 = t(2)-t(1);
n = unique(ceil(logspace(log10(1), log10((N-1)/2), 100).')); % n is the selected discrete values of cluster size
tau = n*t0;
% Computing Allan Deviation
% Allan Deviation Equation DOI 10.1109/TIM.2007.908635
adev = 0;
Y = [];
for i=1:numel(n)
a = 0;
ni = n(i);
for k=1:(N-(2*n(i))+1)
a = a + (((sum(omega(k+n(i):k+n(i)+n(i)-1)/(n(i)*t0)))-(sum(omega(k:k+n(i)-1)/(n(i)*t0))))^2);
end
adev = sqrt((1/(2*(N-(2*n(i))+1)))*a);
Y = [Y; adev];
end
4 Comments
Bruno Luong
on 6 Aug 2023
Moved: Dyuman Joshi
on 8 Sep 2023
" transpose might take a toll on time."
0.2 ms
A=rand(1,1e7); % I believe OP array size is 33 time smaller
tic; A=A.'; toc
Dyuman Joshi
on 6 Aug 2023
Moved: Dyuman Joshi
on 8 Sep 2023
Well, I did say might. But yeah, it's not the case here.
Answers (1)
Bruno Luong
on 6 Aug 2023
Edited: Bruno Luong
on 6 Aug 2023
instead of doing over and over (in the loop on the bottom) such calculation
sum(omega(i1:i2));
you could do once the cumulative sum
I = cumsum([0; omega(:)]);
and then replace sum(omega(i1:i2)) by
I(i2+1)-I(i1) % == sum(omega(i1:i2));
Your loop becomes (EDIT)
Y = zeros(numel(n),1);
I = cumsum([0; omega(:)]);
for i=1:numel(n)
a = 0;
ni = n(i);
for k=1:(N-(2*n(i))+1)
a = a + ((I(k+2*ni)-I(k+ni))/(ni*t0) - (I(k+ni)-I(k))/(n(i)*t0))^2;
end
adev = sqrt((1/(2*(N-(2*ni)+1)))*a);
Y(i) = adev;
end
which in term can be further vectorized (EDIT)
Y = zeros(numel(n),1);
I = cumsum([0; omega(:)]);
for i=1:numel(n)
ni = n(i);
p = N-2*ni+1;
K = 1:p;
Y(i) = 1/(ni*t0*sqrt(2*p)) * norm(I(K+2*ni) - 2*I(K+ni) + I(K));
end
7 Comments
Bruno Luong
on 7 Aug 2023
Edited: Bruno Luong
on 7 Aug 2023
I simply duplicate what your code does.
k=0;
for j=1:1+32
k=k+voltage(j);
end
k=k/33;
Your code compute k as mean of the first window, look at j index of your loop.
If you want the mean of the current windows you should make
for j=i:i+32
...
end
I believe few people ask you about this oddness and potential bug, including me but I delete later the question since you did not answer.
Bruno Luong
on 7 Aug 2023
Edited: Bruno Luong
on 7 Aug 2023
My other question (was deleted so I reapeat here) is that why you use the first value of c in the window to set d
d(l)=c(i);
Is it intentional, and the other value of voltages are used only to compute the mean value k?
If I had to chose one c per window do nuild d, I would rather select the middle point
d(l)=c(i+16);
See Also
Categories
Find more on Semiconductors and Converters in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!