2017-03-14 14 views
-3

2つの円の交点を計算するために次のコードを書いた。コードは単純で十分に速いです。それ以上の最適化は必要ありませんが、このコードをより積極的に最適化することができます。たとえば、h/d1.0/dは2回計算されます(コンパイラの最適化を忘れてみましょう)。コンパイラの最適化をどれだけ信頼できるか?

const std::array<point,2> intersect(const circle& a, 
             const circle& b) { 
    std::array<point,2> intersect_points; 
    const float d2 = squared_distance(a.center, b.center); 
    const float d = std::sqrt(d2); 
    const float r12 = std::pow(a.radious, 2); 
    const float r22 = std::pow(b.radious, 2); 
    const float l = (r12 - r22 + d2)/(2*d); 
    const float h = std::sqrt(r12 - std::pow(l,2)); 
    const float termx1 = (1.0/d) * (b.center.x - a.center.x) + a.center.x; 
    const float termx2 = (h/d)*(b.center.y - a.center.y); 
    const float termy1 = (1.0/d) * (b.center.y - a.center.y) + a.center.y; 
    const float termy2 = (h/d)*(b.center.x - a.center.x); 
    intersect_points[0].x = termx1 + termx2; 
    intersect_points[0].y = termy1 - termy2; 
    intersect_points[1].x = termx1 - termx2; 
    intersect_points[1].y = termy1 + termy2; 
    return intersect_points; 
} 

私の質問は、コードを理解して最終的なバイナリを最適化するために、C++コンパイラ(g ++)をどの程度信頼できるかです。 g ++は1.0/dを2回行うことを避けることができますか?より正確には、どこに行があるかを知りたい。コンパイラーに細かいチューニングを任せて、いつ最適化を行うのですか?

+1

標準ではほとんど最適化については言及していません。コンパイラと提供するフラグによって異なります。 https://godbolt.org/を使用して、特定のコンパイラが出力するものを確認することができます。 –

+2

私は、 'std :: pow(x、2)'を 'x * x'に最適化するコンパイラに頼らないでください。この変更により大幅な改善が得られる可能性があります。 –

+1

* trust *が行く限り、私はそれがそうでないという証拠が出るまで私のコンパイラが正しい結果を生成することを信頼します。出力が予期せぬものであれば、私はすぐにそれが人間のエラーであると仮定します。コンパイラのバグではありません。 –

答えて

1

人気の高いコンパイラは、今日はかなり最適化されています。 オプティマイザは1.0/dのような一般的な式を検出する可能性が高いため、この点については気にしないでください。 std:pow(x, 2)を、オプティマイザがx * xに置き換えた可能性は非常に低くなります。 これは、使用している関数、使用しているコンパイラのバージョン、および最適化コマンドラインスイッチによって異なります。この場合は、x * xと書く方がよいでしょう。 オプティマイザがどれくらい遠くまで行くことができ、人間として引き継がなければならないかは、オプティマイザがどのように「スマート」であるかによって決まります。しかし、経験則として、コンパイラはコード行から差し引くことができるものを最適化することができます。 例: コンパイラは、この用語が常に偽であることを知ります。1 == 2 しかし、これは常に偽であることもわかりません:1 == nextPrimeAfter(1)、したがって、関数nextPrimeAfter()の機能に関する知識が必要です。

関連する問題