2

プロファイラーを実行すると、最も時間がかかるコードは関数であることがわかりますvdist。地球を楕円体と見なして、地球上の 2 点間の距離を測定するプログラムです。コードは標準に見えますが、どこをどのように改善できるかわかりません。最初のコメントによると、既にベクトル化されています。MEX ファイルとして使用できる他の言語に対応するものはありますか。私が望むのは、時間効率の面での改善です。これは、Matlab FEX からのコードへのリンクです。

http://www.mathworks.com/matlabcentral/fileexchange/8607-vectorized-geodetic-distance-and-azimuth-on-the-wgs84-earth-ellipsoid/content/vdist.m

関数はループ内から次のように呼び出されます (ここで最も時間のかかる行として関数を見つけることができます)。

              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 
4

2 に答える 2

2

投稿されたコードをいくら調べてもvdist、ループ内で の呼び出しが行われる理由がわかりません。

ループ内のコード ブロックを最適化しようとするとき、私が探すものの 1 つは、不変であるステートメント、つまり、各呼び出しで同じであり、したがってループから持ち上げることができるステートメントです。

見つめている

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 

そうですか

  • l131 では、変数p0,NV1は rhs にのみ出現し、ループ内の他の場所の rhs にのみ出現するため、このステートメントはループ不変であり、ループから持ち上げることができます。おそらくわずかな時間の節約です。
  • l134 では、別のループ不変のステートメントが表示されます。これは、別の小さな時間節約のためにループから再び持ち上げることができます。
  • しかし、その後、私は非常に詳しく調べ始めました。呼び出しが行われるl132がループ内にある理由もわかりませんvdist。その割り当ての rhs の値はループ内で変更され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 
于 2012-10-26T09:38:29.460 に答える
1

この FEX ファイルを GPU で使用できるように書き換えるオプションがあります。たとえば、 Jacketと呼ばれるツールボックスがスムーズな方法です。

于 2012-10-25T15:42:31.730 に答える