在 MATLAB 中向量化 for 循环
我不太确定这是否可行,但我对 MATLAB 的理解肯定会更好。
我有一些代码希望进行矢量化,因为它在我的程序中造成了相当大的瓶颈。它是优化例程的一部分,该例程具有多种可能的短期平均值 (STA)、长期平均值 (LTA) 和灵敏度 (OnSense) 配置可供运行。
时间采用矢量格式,FL2onSS 是主要数据(Nx1 双精度),FL2onSSSTA 是其 STA(NxSTA 双精度),FL2onSSThresh 是其阈值(NxLTAxOnSense 双精度)。
想法是计算 4D 的红色警报矩阵 - AlarmStatexSTAxLTAxOnSense 在程序的其余部分中使用。
Red = zeros(length(FL2onSS), length(STA), length(LTA), length(OnSense), 'double');
for i=1:length(STA)
for j=1:length(LTA)
for k=1:length(OnSense)
Red(:,i,j,k) = calcRedAlarm(Time, FL2onSS, FL2onSSSTA(:,i), FL2onSSThresh(:,j,k));
end
end
end
我目前已经重复了一个函数,试图提高它的速度,但显然如果整个事情可以矢量化会更好。换句话说,如果有更好的解决方案,我不需要保留该功能。
function [Red] = calcRedAlarm(Time, FL2onSS, FL2onSSSTA, FL2onSSThresh)
% Calculate Alarms
% Alarm triggers when STA > Threshold
zeroSize = length(FL2onSS);
%Precompose
Red = zeros(zeroSize, 1, 'double');
for i=2:zeroSize
%Because of time chunks being butted up against each other, alarms can
%go off when they shouldn't. To fix this, timeDiff has been
%calculated to check if the last date is different to the current by 5
%seconds. If it isn't, don't generate an alarm as there is either a
%validity or time gap.
timeDiff = etime(Time(i,:), Time(i-1,:));
if FL2onSSSTA(i) > FL2onSSThresh(i) && FL2onSSThresh(i) ~= 0 && timeDiff == 5
%If Short Term Avg is > Threshold, Trigger
Red(i) = 1;
elseif FL2onSSSTA(i) < FL2onSSThresh(i) && FL2onSSThresh(i) ~= 0 && timeDiff == 5
%If Short Term Avg is < Threshold, Turn off
Red(i) = 0;
else
%Otherwise keep current state
Red(i) = Red(i-1);
end
end
end
代码很简单,所以我不会进一步解释。如果您需要说明特定线路正在做什么,请告诉我。
I'm not too sure if this is possible, but my understanding of MATLAB could certainly be better.
I have some code I wish to vectorize as it's causing quite a bottleneck in my program. It's part of an optimisation routine which has many possible configurations of Short Term Average (STA), Long Term Average (LTA) and Sensitivity (OnSense) to run through.
Time is in vector format, FL2onSS is the main data (an Nx1 double), FL2onSSSTA is its STA (NxSTA double), FL2onSSThresh is its Threshold value (NxLTAxOnSense double)
The idea is to calculate a Red alarm matrix which will be 4D - the alarmStatexSTAxLTAxOnSense that is used throughout the rest of the program.
Red = zeros(length(FL2onSS), length(STA), length(LTA), length(OnSense), 'double');
for i=1:length(STA)
for j=1:length(LTA)
for k=1:length(OnSense)
Red(:,i,j,k) = calcRedAlarm(Time, FL2onSS, FL2onSSSTA(:,i), FL2onSSThresh(:,j,k));
end
end
end
I've currently got this repeating a function in an attempt to get a bit more speed out of it, but obviously it will be better if the entire thing can be vectorised. In other words I do not need to keep the function if there is a better solution.
function [Red] = calcRedAlarm(Time, FL2onSS, FL2onSSSTA, FL2onSSThresh)
% Calculate Alarms
% Alarm triggers when STA > Threshold
zeroSize = length(FL2onSS);
%Precompose
Red = zeros(zeroSize, 1, 'double');
for i=2:zeroSize
%Because of time chunks being butted up against each other, alarms can
%go off when they shouldn't. To fix this, timeDiff has been
%calculated to check if the last date is different to the current by 5
%seconds. If it isn't, don't generate an alarm as there is either a
%validity or time gap.
timeDiff = etime(Time(i,:), Time(i-1,:));
if FL2onSSSTA(i) > FL2onSSThresh(i) && FL2onSSThresh(i) ~= 0 && timeDiff == 5
%If Short Term Avg is > Threshold, Trigger
Red(i) = 1;
elseif FL2onSSSTA(i) < FL2onSSThresh(i) && FL2onSSThresh(i) ~= 0 && timeDiff == 5
%If Short Term Avg is < Threshold, Turn off
Red(i) = 0;
else
%Otherwise keep current state
Red(i) = Red(i-1);
end
end
end
The code is simple enough so I won't explain it any further. If you need elucidation on what a particular line is doing, let me know.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
诀窍是将所有数据转化为相同的形式,主要使用repmat 和permute。那么逻辑就是简单的部分。
我需要一个令人讨厌的技巧来实现最后一部分(如果没有一个条件成立,则使用最后的结果)。通常这种逻辑是使用 cumsum 完成的。我必须使用另一个 2.^n 矩阵来确保使用定义的值(这样 +1,+1,-1 将真正给出 1,1,0) - 只需看看代码:)
The trick is to bring all your data to the same form, using mostly repmat and permute. Then the logic is the simple part.
I needed a nasty trick to implement the last part (if none of the conditions hold, use the last results). usually that sort of logic is done using a cumsum. I had to use another matrix of 2.^n to make sure the values that are defined are used (so that +1,+1,-1 will really give 1,1,0) - just look at the code :)