Optimise function with datetime operations

Hi I have a function which is doing simple operations in a large file. I ran the profiler and it seems like most the time has been spent in datetime operaitons. See code below:
function batterystatus = freqdataV3( freq, date,FFRExcWindow1, FFRExcWindow2, REDstart, REDend, batpower, batenergy, batinitial , batefficiency)
Energy0 = batenergy * batinitial;
uplimit = 50.015;
lowlimit = 49.985;
statuplimit = 50.5;
statlowlimit = 49.5;
batterystatus(:,7) = freq;
batterystatus(1 ,1) = Energy0;
batterystatus(1, 2) = 0;
batterystatus(1, 3) = 0;
batterystatus(1, 4) = 0;
batterystatus(1, 5) = 0;
batterystatus(1, 6) = 0;
FFRfinishdate = datetime(year(date), month(date), day(date),floor(FFRExcWindow1), rem(FFRExcWindow1, 1) * 60, 0);
FFRstartdate = datetime(year(date), month(date), day(date),floor(FFRExcWindow2), rem(FFRExcWindow2, 1) * 60, 0);
REDstartdate = datetime(year(date), month(date), day(date), floor(REDstart), rem(REDstart, 1) * 60,0);
REDenddate = datetime(year(date), month(date), day(date), floor(REDend), rem(REDend, 1) * 60,0);
for i = 2:numel(freq)
if weekday(date(i)) >= 2 && weekday(date(i)) <= 6 && ge(date(i),FFRfinishdate(i)) && lt(date(i),REDstartdate(i))
if batterystatus(i - 1, 1) >= (batenergy - 1)
batterystatus(i ,1:6 ) = batterystatus(i -1 ,1:6 );
else
(...)
When I run the profiler, it highlights the "if weekday(date(i))..." in RED. The whole function has a few more "if"s below, but they similar to the one above but with different conditions. The profiler shows that almost half the total time is due to datetime.subsref. Is this just to perform datetime operations such as "ge" and "lt"? If so, is there any clever away around it that would save me time to run it?
Thanks in advance.

 Accepted Answer

Assuming "date" is a datetime array, a couple things as a starting point:
1) The creation of the FFR and RED arrays looks like they could be cleaned up with something like
dateshift(date,'start','day') + hours(FFRExcWindow1)
but hard to say for sure. This won't speed things up but it will be easier to understand.
2) Your comparisons are doing calendar arithmetic, which is inherently expensive, especially if time zones are involved (can't tell). Don't calculate the weekday twice. Actually, don't use weekday at all, it is an older function intended for datenum inputs. Use day(date,'dayofweek'). Also, use isbetween instead of gt and lt. Actually, it may be that you've used ge and lt because you want a half-open interval. Fair enough.
3) I can't tell for sure but it looks like you are finding events that happened between certain times only on weekdays. It may be faster if you call timeofday on the original datetimes and compare those to the endpoints of your window, converted to hours. Hard to say for sure.
3) I can't say for sure if you can vectorize your entire loop, but you can certainly vectorize those conditions. Calculate, once,
dow = day(date,'dayofweek');
tod = timeofday(date);
isWeekdayInWindow = (2 <= dow & dow <= 6) & (FFRExcWindow2 <= tid & tod < REDstart)
Or something like that. Then use that logical to replace the entire condition in your if statement. If you can vectorize the entire loop, even better.

1 Comment

Hi Peter,
I vectorized all my conditions and this helped a lot! I can now run the code through 10m lines in 25 seconds.
Thanks!

Sign in to comment.

More Answers (0)

Categories

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!