Оптимизация векторизованной функции Matlab
Когда я запускаю профилировщик, он говорит мне, что самым трудоемким кодом является функция vdist
, Это программа, которая измеряет расстояние между двумя точками на земле, рассматривая Землю как эллипсоид. Код выглядит стандартно, и я не знаю, где и как его можно улучшить. В первоначальных комментариях говорится, что оно уже векторизовано. Есть ли аналог на другом языке, который можно использовать в качестве файла MEX? Все, что я хочу, это улучшение с точки зрения эффективности времени. Вот ссылка на код от Matlab FEX.
Функция вызывается из цикла как- (Вы можете найти функцию как ее наиболее трудоемкую строку здесь)
109 for i=1:polySize
110 % find the two vectors needed
11755 111 if i~=1
0.02 11503 112 if i<polySize
0.02 11251 113 p0=Polygon(i,:); p1=Polygon(i-1,:); p2=Polygon(i+1,:);
252 114 else
252 115 p0=Polygon(i,:); p1=Polygon(i-1,:); p2=Polygon(1,:); %special case for i=polySize
252 116 end
252 117 else
252 118 p0=Polygon(i,:); p1=Polygon(polySize,:); p2=Polygon(i+1,:); %special case for i=1
252 119 end
0.02 11755 120 Vector1=(p0-p1); Vector2=(p0-p2);
0.06 11755 121 if ~(isequal(Vector1,Vector2) || isequal(Vector1,ZeroVec) || isequal(Vector2,ZeroVec));
122 %determine normals and normalise and
0.17 11755 123 NV1=rotateVector(Vector1, pi./2); NV2=rotateVector(Vector2, -pi./2);
0.21 11755 124 NormV1=normaliseVector(NV1); NormV2=normaliseVector(NV2);
125 %determine rotation by means of the atan2 (because sign matters!)
11755 126 totalRotation = vectorAngle(NormV2, NormV1); % Bestimme den Winkel totalRotation zwischen den normierten Vektoren
11755 127 if totalRotation<10
11755 128 totalRotation=totalRotation*50;
11755 129 end
0.01 11755 130 for res=1:6
0.07 70530 131 U_neu=p0+NV1;
17.01 70530 132 [pos,a12] = vdist(p0(:,2),p0(:,1),U_neu(:,2),U_neu(:,1));
0.02 70530 133 a12=a12+1/6.*res*totalRotation;
70530 134 ddist=1852*safety_distance;
4.88 70530 135 [lat2,lon2] = vreckon(p0(:,2),p0(:,1),ddist, a12);
0.15 70530 136 extendedPoly(f,:)=[lon2,lat2];f=f+1;
< 0.01 70530 137 end
11755 138 end
11755 139 end
2 ответа
Независимо от того, как сильно я изучаю код, который был опубликован, я не могу понять, почему вызов vdist
сделано внутри петли.
Когда я пытаюсь оптимизировать блок кода внутри цикла, одной из вещей, которые я ищу, являются операторы, которые являются инвариантными, то есть одинаковыми при каждом вызове, и которые, следовательно, могут быть выведены из цикла.
Смотря на
130 for res=1:6
131 U_neu=p0+NV1;
132 [pos,a12] = vdist(p0(:,2),p0(:,1),U_neu(:,2),U_neu(:,1));
133 a12=a12+1/6.*res*totalRotation;
134 ddist=1852*safety_distance;
135 [lat2,lon2] = vreckon(p0(:,2),p0(:,1),ddist, a12);
136 extendedPoly(f,:)=[lon2,lat2];f=f+1;
137 end
я вижу
- в 131 переменные
p0
,NV1
появляются только в правой части, и они появляются только в правой части в другом месте цикла, поэтому этот оператор является инвариантным к циклу и может быть выведен из цикла; возможно, только небольшая экономия времени; - снова в l134 я вижу другой оператор, инвариантный к циклу, который снова может быть выведен из цикла для еще одной небольшой экономии времени;
- но потом я начал присматриваться, и я не понимаю, почему
vdist
сделано, находится внутри цикла либо. Ни одно из значений в правой части этого назначения не изменяется в цикле (кромеU_neu
но я уже поднял это из цикла).
Приведу в порядок то, что осталось немного, вот чем я закончил:
U_neu=p0+NV1;
[pos,a12] = vdist(p0(:,2),p0(:,1),U_neu(:,2),U_neu(:,1));
ddist=1852*safety_distance;
for res=1:6
extendedPoly(f,:) = vreckon(p0(:,2),p0(:,1),ddist, a12+1/6.*res*totalRotation);
f=f+1;
end
Можно будет переписать этот FEX-файл таким образом, чтобы вы могли использовать его для графических процессоров. Например, плавный путь к нему - это набор инструментов под названием Jacket.