Efficient and quick way to summation of large data points
3 ビュー (過去 30 日間)
古いコメントを表示
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 件のコメント
Bruno Luong
2023 年 8 月 6 日
移動済み: Dyuman Joshi
2023 年 9 月 8 日
" 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
2023 年 8 月 6 日
移動済み: Dyuman Joshi
2023 年 9 月 8 日
Well, I did say might. But yeah, it's not the case here.
回答 (1 件)
Bruno Luong
2023 年 8 月 6 日
編集済み: Bruno Luong
2023 年 8 月 6 日
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 件のコメント
Bruno Luong
2023 年 8 月 7 日
編集済み: Bruno Luong
2023 年 8 月 7 日
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
2023 年 8 月 7 日
編集済み: Bruno Luong
2023 年 8 月 7 日
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);
参考
カテゴリ
Help Center および File Exchange で Semiconductors and Converters についてさらに検索
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!