slow for and while loops
显示 更早的评论
Hi all, I'm running those lines that suppose to run on two tables (T2 and T1) and check if the difference in the first column is less than coinc_win. both columns in the tables are data from the same clock and I want the code to match line from table T2 to the correspond lines in table T1 and write the lines to T3. this is what I've written so far, but it runs pretty slow, anyone has suggestions how to improve it?
coinc_win = 500;
correction = 150;
j = 1;
r = 1;
tic
for i = 1: height(T2(:,1))
while j <= height(T1(:,1))
while (T2.time(i)+correction) - T1.time(j) > coinc_win || T2.time(i)+correction > T1.time(j)
j = j+1;
break;
end
while T2.time(i) - T1.time(j) < coinc_win && (T2.time(i)+correction) > T1.time(j)
T3.deltaT(r) = T2.time(i) - T1.time(j);
T3.energy_G(r) = T2.E(i);
T3.energy_S(r) = T1.E(j);
r= r+1;
j = j+1;
end
if T2.time(i) < T1.time(j)
break;
end
end
end
toc
12 个评论
Jakob B. Nielsen
2020-1-21
No real thoughts right off the bat. You could try the "Run and Time" profiler, see which functions eat up most of your time, and then look to improve those.
Looky
2020-1-21
There are a few things I don't understand about your code. Maybe you can clarify on these:
coinc_win = 500;
correction = 150;
j = 1;
r = 1;
tic
for i = 1: height(T2(:,1))
while j <= height(T1(:,1))
while (T2.time(i)+correction) - T1.time(j) > coinc_win || T2.time(i)+correction > T1.time(j)
% What is the purpose of this loop? It always breaks after the first Iteration, making it more like
% an if statement. If that is intended, use if statement instead.
% Also, part of the condition is redundant.
% If the first part (T2.time(i)+correction) - T1.time(j) > coinc_win evaluates true, the second
% part must always be true anyway. The first part has therefore no affect since the second part already
% includes this case. Check the condition!
% What is the purpose behind this loop?
j = j+1;
break;
end
while T2.time(i) - T1.time(j) < coinc_win && (T2.time(i)+correction) > T1.time(j)
T3.deltaT(r) = T2.time(i) - T1.time(j);
T3.energy_G(r) = T2.E(i);
T3.energy_S(r) = T1.E(j);
r= r+1;
j = j+1;
end
if T2.time(i) < T1.time(j)
break;
end
end
end
toc
sani
2020-1-21
Looky
2020-1-21
So, first of all, you should be aware that matlab isn't really made for iterating through arrays with this sort of loops, instead it excels at using vectorization to speed things up. But if your tables aren't too huge, your code shouldn't be too slow. Maybe you can publish some example data. It would help to see the code in action and get a feeling for what you mean by "pretty slow".
IF is not a loop, it is just for checking a condition. In your case the while loop (under which I commented above) checks a condition, increments j and than breaks immediately. This is nothing else than checking a condition. This is more abour readibility of your code then it is about performance.
But I have to add that your code has some issues:
You increment j in your while loop
while T2.time(i) - T1.time(j) < coinc_win && (T2.time(i)+correction) > T1.time(j)
T3.deltaT(r) = T2.time(i) - T1.time(j);
T3.energy_G(r) = T2.E(i);
T3.energy_S(r) = T1.E(j);
r= r+1;
j = j+1;
end
but you are never checking if T1.time is long enough. This can lead to exceeds matrix dimensions errors when reaching the bottom of your table.
Another potential error is, that j is only increment within while loops. Problem with this is that it is difficult to make sure, that your outer while loop ( while j <= height(T1(:,1)) ) is not getting stuck in an infinite loop. I think in your case you can get away with this, because of the structure of your data, but it really is a dangerous issue.
Another issue you might want to think about is that some of the values from T2 are skipped if they are to close to each other (closer than correction variable). Did you check the values in T3 if they show what you would expect?
Maybe you can write out some of the data you expect for a small example?
Guillaume
2020-1-21
@sani, can you explain what you want to do, not in term of code but in term of goal. I.E don't tell us you want to iterate but tell us, I want to extract xxx from T2 where its time matches that of T1 and calculate the mean of yyy or some such.
It is most likely that whatever you want to do can be achieved more easily without any loop.
Also, note that height(T2(:,1)) is a convoluted (and marginally slower) way of writing height(T2).
sani
2020-1-21
Mohammad Sami
2020-1-23
I assume you are trying to match the two tables by timestamps.
If that is true, you can create two timetables instead of tables.
Thereafter use the synchronize (R2016b onwards) function to join the two tables together.
The function allows you control how exactly the two tables are synchronised.
Thereafter it should be simpler to compare the data from two tables without any loops.
Guillaume
2020-1-23
Yes, as Mohammad stated timetables and synchronize should be able to help. I assume that the time is the first column in your two files but it's not clear what encoding it uses. Can you explain?
Otherwise, ismembertol would be a lot faster than than your double while loops. But in the first place, I'd recommend going with timetables as they have other benefits that may be of use to you.
sani
2020-1-24
Mohammad Sami
2020-1-24
timetables can accept either datetime format or duration format. you can convert to duration as follows.
H = 0;
MI = 0;
S = 0;
MS = NS ./ 1000; % NS can be an array of nanoseconds
D = duration(H,MI,S,MS)
sani
2020-1-24
Guillaume
2020-1-24
A much simpler way to convert a numeric array in nanoseconds to a duration type is with:
dur = seconds(NS * 1e-9);
See example code in my answer.
采纳的回答
更多回答(0 个)
类别
在 帮助中心 和 File Exchange 中查找有关 Data Type Identification 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!