283

現在GCCを使用していますが、最近Clangを発見し、切り替えについて考えています。ただし、決定要因が1つあります-生成するバイナリの品質(速度、メモリフットプリント、信頼性)gcc -O3-1%速く実行されるバイナリを生成できる場合、またはClangバイナリがより多くのメモリを消費するか、コンパイラのバグが原因で失敗する場合、それは取引です-ブレーカ。

Clangは、GCCよりも優れたコンパイル速度と低いコンパイル時のメモリフットプリントを誇っていますが、コンパイルされたソフトウェアのベンチマーク/比較に本当に興味があります-既存のリソースまたは独自のベンチマークを教えていただけますか?

4

7 に答える 7

286

これは、GCC4.7.2およびC++用のClang3.2を使用した私の調査結果ではありますが、最新のものです。

更新:GCC 4.8.1 vclang3.3の比較を以下に追加。

更新:GCC 4.8.2 vclang3.4の比較がそれに追加されます。

私は、GCCとClangの両方を備えたLinux用に構築されたOSSツールと、Windows用のMicrosoftのコンパイラを維持しています。ツールcoanは、C / C++ソースファイルとそのコードラインのプリプロセッサおよびアナライザーです。再帰下降構文解析とファイル処理を専攻する計算プロファイルです。開発ブランチ(これらの結果が関係する)は、現在、約90個のファイルに約11KLOCで構成されています。現在、ポリモーフィズムとテンプレートが豊富なC ++でコーディングされていますが、ハッキングされたCでのそれほど遠くない過去によって、多くのパッチでまだ悩まされています。移動セマンティクスは明示的に利用されていません。シングルスレッドです。私はそれを最適化するために真剣な努力をしていませんが、「アーキテクチャ」は非常に大部分がToDoのままです。

私は3.2より前のClangを実験的なコンパイラとしてのみ使用しました。これは、その優れたコンパイル速度と診断にもかかわらず、C++11標準サポートがcoanによって行使される点で現代のGCCバージョンに遅れをとっていたためです。3.2では、このギャップは埋められました。

現在のcoan開発用の私のLinuxテストハーネスは、1ファイルパーサーテストケース、数千のファイルを消費するストレステスト、および1K未満のファイルを消費するシナリオテストの混合で約70Kのソースファイルを処理します。

ハーネスは、テスト結果を報告するだけでなく、消費されたファイルの合計とcoanで消費された実行時間を累積して表示します(各coanコマンドラインをLinuxtimeコマンドに渡し、報告された数をキャプチャして合計します)。測定可能な時間が0のテストがいくつあっても、合計で0になるという事実によって、タイミングはお世辞になりますが、そのようなテストの寄与はごくわずかです。タイミング統計は、次のmake checkように最後に表示されます。

coan_test_timer: info: coan processed 70844 input_files.
coan_test_timer: info: run time in coan: 16.4 secs.
coan_test_timer: info: Average processing time per input file: 0.000231 secs.

テストハーネスのパフォーマンスをGCC4.7.2とClang3.2の間で比較しましたが、コンパイラーを除いてすべて同じです。Clang 3.2以降、GCCがコンパイルするコードトラクトとClangの代替コードをプリプロセッサで区別する必要がなくなりました。いずれの場合も同じC++ライブラリ(GCC)を構築し、同じターミナルセッションですべての比較を連続して実行しました。

私のリリースビルドのデフォルトの最適化レベルは-O2です。また、-O3でビルドをテストすることに成功しました。各構成を3回続けてテストし、3つの結果を平均して、次の結果を得ました。データセル内の数値は、約70Kの入力ファイル(出力と診断の読み取り、解析、書き込み)のそれぞれを処理するためにcoan実行可能ファイルによって消費されるマイクロ秒の平均数です。

          | -O2 | -O3 |O2/O3|
----------|-----|-----|-----|
GCC-4.7.2 | 231 | 237 |0.97 |
----------|-----|-----|-----|
Clang-3.2 | 234 | 186 |1.25 |
----------|-----|-----|------
GCC/Clang |0.99 | 1.27|

特定のアプリケーションには、コンパイラの長所または短所に不当に作用する特性がある可能性が非常に高くなります。厳密なベンチマークでは、さまざまなアプリケーションが採用されています。そのことを十分に念頭に置いて、これらのデータの注目すべき機能は次のとおりです。

  1. -O3の最適化はGCCにわずかに有害でした
  2. -O3の最適化はClangにとって非常に有益でした
  3. -O2最適化では、GCCはウィスカーだけでClangよりも高速でした
  4. -O3最適化では、ClangはGCCよりも重要な速さでした。

2つのコンパイラのさらに興味深い比較は、これらの発見の直後に偶然に現れました。Coanは、スマートポインターを自由に使用しており、その1つがファイル処理で頻繁に実行されます。この特定のスマートポインター型は、コンパイラーの差別化のために以前のリリースでtypedefされていました。これはstd::unique_ptr<X>、構成されたコンパイラーがその使用法を十分に成熟してサポートしている場合、またはそうでない場合std::shared_ptr<X>です。std::unique_ptrこれらのポインタは実際に転送されたため、へのバイアスは愚かでしたが、C++11バリアントが私にとって斬新だった時点std::unique_ptrで置き換えるためのより適切なオプションのように見え ました。std::auto_ptr

これと同様の差別化に対するClang3.2の継続的な必要性を評価するための実験的なビルドの過程で、ビルドする std::shared_ptr<X>つもりだったときに誤ってビルドしましたstd::unique_ptr<X>が、デフォルトの-O2最適化を使用した結果の実行可能ファイルが最速であることに驚きました。見たことがあり、184ミリ秒を達成することもありました。入力ファイルごと。この1つのソースコードの変更により、対応する結果は次のようになりました。

          | -O2 | -O3 |O2/O3|
----------|-----|-----|-----|
GCC-4.7.2 | 234 | 234 |1.00 |
----------|-----|-----|-----|
Clang-3.2 | 188 | 187 |1.00 |
----------|-----|-----|------
GCC/Clang |1.24 |1.25 |

ここでの注意点は次のとおりです。

  1. 現在、どちらのコンパイラも-O3最適化の恩恵を受けていません。
  2. Clangは、最適化の各レベルで同様に重要なことにGCCを上回っています。
  3. GCCのパフォーマンスは、スマートポインターのタイプの変更によってわずかに影響を受けるだけです。
  4. Clangの-O2パフォーマンスは、スマートポインターのタイプの変更によって重要な影響を受けます。

スマートポインタータイプの変更の前後で、Clangは-O3最適化で大幅に高速な実行可能ファイルを構築でき、そのポインタータイプが最適な場合は-O2と-O3で同等に高速な実行可能ファイルを構築できますstd::shared_ptr<X>---仕事で。

私がコメントする能力がない明らかな質問は 、GCCが無関心であるのに、頻繁に使用されるスマートポインタータイプが一意から共有に変更されたときに、Clangがアプリケーションで25%の-O2スピードアップを見つけることができる理由です。同じ変化に。また、Clangの-O2最適化が、私のスマートポインターの選択の知恵に非常に敏感であるという発見を応援するべきか、それとも後押しするべきかどうかもわかりません。

更新:GCC 4.8.1 v clang 3.3

対応する結果は次のとおりです。

          | -O2 | -O3 |O2/O3|
----------|-----|-----|-----|
GCC-4.8.1 | 442 | 443 |1.00 |
----------|-----|-----|-----|
Clang-3.3 | 374 | 370 |1.01 |
----------|-----|-----|------
GCC/Clang |1.18 |1.20 |

4つの実行可能ファイルすべてが1つのファイルを処理するのに以前よりもはるかに長い平均時間を要するという事実は、最新のコンパイラーのパフォーマンスには反映されません。これは、テストアプリケーションの後の開発部門が、その間に多くの高度な解析を行い、その代償を払っているという事実によるものです。比率だけが重要です。

現在の注目点は、驚くほど斬新ではありません。

  • GCCは-O3最適化に無関心です
  • clangは-O3最適化の恩恵をほとんど受けません
  • clangは、最適化の各レベルで同様に重要なマージンでGCCを上回っています。

これらの結果をGCC4.7.2およびclang3.2の結果と比較すると、GCCが各最適化レベルでclangのリードの約4分の1を取り戻していることがわかります。しかし、その間にテストアプリケーションが大幅に開発されたため、これをGCCのコード生成のキャッチアップに自信を持って帰することはできません。(今回は、タイミングを取得したアプリケーションのスナップショットをメモして、再度使用できるようにしました。)

更新:GCC 4.8.2 v clang 3.4

GCC 4.8.1 v Clang 3.3のアップデートを終了し、今後のアップデートでは同じcoansnaphotに固執すると述べました。しかし、代わりに、そのスナップショット(rev。301)、テストスイート(rev。619)に合格した最新の開発スナップショットでテストすることにしました。これは結果に少し経度を与えます、そして私は別の動機を持っていました:

私の最初の投稿は、私が速度のためにcoanを最適化することに何の努力も捧げていなかったことを指摘しました。これは、revの時点でも当てはまりました。301.しかし、タイミング装置をcoanテストハーネスに組み込んだ後、テストスイートを実行するたびに、最新の変更によるパフォーマンスへの影響に直面しました。それはしばしば驚くほど大きく、機能性の向上によってメリットがあると感じたよりも、傾向が急激にネガティブであることがわかりました。

回転によって。308テストスイートの入力ファイルあたりの平均処理時間は、ここに最初に投稿してから2倍以上になりました。その時点で、私はパフォーマンスを気にしないという私の10年間の方針をUターンしました。619までの改訂が集中的に行われる中で、パフォーマンスは常に考慮事項であり、それらの多くは、基本的に高速な回線で主要なロードベアラーを書き換えることに専念していました(ただし、非標準のコンパイラ機能を使用することはありませんでした)。このUターンに対する各コンパイラの反応を見るのは興味深いでしょう。

これは、最新の2つのコンパイラによるrev.301のビルドでおなじみのタイミングマトリックスです。

coan-rev.301の結果

          | -O2 | -O3 |O2/O3|
----------|-----|-----|-----|
GCC-4.8.2 | 428 | 428 |1.00 |
----------|-----|-----|-----|
Clang-3.4 | 390 | 365 |1.07 |
----------|-----|-----|------
GCC/Clang | 1.1 | 1.17|

ここでの話は、GCC-4.8.1とClang-3.3からわずかに変更されています。GCCの表示はささいなことです。Clang'sはささいなことです。ノイズがこれを十分に説明している可能性があります。Clangはまだ先を行って-O2おり、-O3マージンはほとんどのアプリケーションでは重要ではありませんが、かなりの数のアプリケーションで重要になります。

そして、これがrevのマトリックスです。619。

coan-rev.619の結果

          | -O2 | -O3 |O2/O3|
----------|-----|-----|-----|
GCC-4.8.2 | 210 | 208 |1.01 |
----------|-----|-----|-----|
Clang-3.4 | 252 | 250 |1.01 |
----------|-----|-----|------
GCC/Clang |0.83 | 0.83|

301と619の数字を並べると、いくつかの点がわかります。

  • 私はより高速なコードを書くことを目指していましたが、どちらのコンパイラーも私の努力を強調しています。だが:

  • GCCは、これらの努力をClangよりもはるかに寛大に返済します。最適化では-O2 、Clangの619ビルドは301ビルドよりも46%高速です-O3。Clangの改善では31%です。良いですが、各最適化レベルで、GCCの619ビルドは301の2倍以上高速です。

  • GCCは、Clangの以前の優位性を覆す以上のものです。そして、各最適化レベルで、GCCはClangを17%上回っています。

  • 最適化からGCCよりも多くのレバレッジを取得する301ビルドでのClangの機能は-O3、619ビルドではなくなりました。どちらのコンパイラも。から意味のある利益を得ることができません-O3

この運命の逆転に私は十分に驚いたので、誤ってclang 3.4自体のビルドが遅くなったのではないかと思いました(ソースからビルドしたため)。そこで、ディストリビューションのストックであるClang3.3を使用して619テストを再実行しました。結果は3.4の場合と実質的に同じでした。

したがって、Uターンへの反応に関して:ここでの数値では、Clangは、助けを与えていないときに、C++コードからの絞り込み速度でGCCよりもはるかに優れています。私が支援することに心を向けたとき、GCCはClangよりもはるかに優れた仕事をしました。

私はその観察を原則に昇格させませんが、「どのコンパイラがより良いバイナリを生成するか」という教訓を取ります。答えが相対的なテストスイートを指定したとしても、バイナリのタイミングを調整するだけの明確な問題ではないという質問です。

あなたのより良いバイナリは最速のバイナリですか、それとも安価に作成されたコードを最もよく補償するものですか? または、保守性と速度よりも再利用を優先する、高価に作成されたコードを最もよく補償しますか?それは、バイナリを生成する動機の性質と相対的な重み、およびそれを行う際の制約に依存します。

いずれにせよ、「最高の」バイナリの構築に深く関心がある場合は、コンパイラの連続した反復が、コードの連続した反復で「最良」のアイデアをどのように実現するかを確認し続ける必要があります。

于 2013-02-23T18:08:13.827 に答える
51

Phoronixはこれについていくつかのベンチマークを行いましたが、これは数か月前のClang/LLVMのスナップショットバージョンに関するものです。その結果、物事は多かれ少なかれプッシュされました。GCCもClangも、すべての場合で決定的に優れているわけではありません。

最新のClangを使用するので、関連性が少し低くなる可能性があります。繰り返しになりますが、GCC 4.6は、明らかにCore2Corei7に対していくつかの主要な最適化を行う予定です。

Clangのより速いコンパイル速度は、元の開発者にとってより良いと思います。そして、コードを世界にプッシュすると、Linuxディストリビューション、BSDなどのエンドユーザーはより速いバイナリーにGCCを使用します。

于 2010-07-06T15:14:11.310 に答える
19

Clangがコードをより速くコンパイルするという事実は、結果のバイナリの速度ほど重要ではないかもしれません。ただし、ここに一連のベンチマークがあります

于 2010-07-06T15:14:31.487 に答える
12

結果のバイナリの速度に関して、GCC4.8とClang3.3の全体的な違いはほとんどありません。ほとんどの場合、両方のコンパイラによって生成されたコードは同様に実行されます。これらの2つのコンパイラのどちらももう一方を支配しません。

GCCとClangの間に大きなパフォーマンスギャップがあることを示すベンチマークは偶然です。

プログラムのパフォーマンスは、コンパイラの選択によって影響を受けます。開発者または開発者のグループがGCCのみを使用している場合、プログラムはClangよりもGCCの方がわずかに高速に実行され、その逆も可能です。

開発者の観点から見ると、GCC4.8+とClang3.3の顕著な違いは、GCCに-Ogコマンドラインオプションがあることです。このオプションを使用すると、デバッグに干渉しない最適化が可能になるため、たとえば、正確なスタックトレースを常に取得できます。Clangにこのオプションがないため、一部の開発者はclangを最適化コンパイラとして使用するのが難しくなります。

于 2013-08-29T17:56:26.163 に答える
10

GCC5.2.1とClang3.6.2で私が指摘した特有の違いは、次のようなクリティカルループがある場合です。

for (;;) {
    if (!visited) {
        ....
    }
    node++;
    if (!*node)
        break;
}

次に、GCCは、-O3または-O2でコンパイルするときに、ループを8回投機的に展開します。Clangはそれをまったく展開しません。試行錯誤の結果、プログラムデータを使用した特定のケースでは、適切な展開量が5であるため、GCCがオーバーシュートし、Clangがアンダーシュートしていることがわかりました。ただし、オーバーシュートはパフォーマンスに悪影響を与えるため、ここではGCCのパフォーマンスが大幅に低下しました。

展開の違いが一般的な傾向なのか、それとも私のシナリオに固有のものなのかはわかりません。

しばらく前に、Cでのパフォーマンスの最適化について詳しく学ぶために、いくつかのガベージコレクターを作成しました。得られた結果は、Clangをわずかに支持するのに十分なほど頭に浮かびます。特にガベージコレクションは主にポインタの追跡とメモリのコピーに関するものであるためです。

結果は次のとおりです(秒単位の数値):

+---------------------+-----+-----+
|Type                 |GCC  |Clang|
+---------------------+-----+-----+
|Copying GC           |22.46|22.55|
|Copying GC, optimized|22.01|20.22|
|Mark & Sweep         | 8.72| 8.38|
|Ref Counting/Cycles  |15.14|14.49|
|Ref Counting/Plain   | 9.94| 9.32|
+---------------------+-----+-----+

これはすべて純粋なCコードであり、C++コードをコンパイルするときのどちらのコンパイラーのパフォーマンスについても主張しません。

Ubuntu 15.10 (Wily Werewolf)、 x86.64 、およびAMD Phenom IIX61090Tプロセッサ。

于 2016-06-12T16:45:32.463 に答える
8

これを判断する唯一の方法は、試してみることです。FWIW、AppleのLLVM GCC 4.2を使用すると、通常のGCC 4.2(SSEが非常に多いx86-64コードの場合)と比較して非常に優れた改善が見られましたが、コードベースが異なる場合はYMMVです。

x86 / x86-64を使用していて、最後の数パーセントを本当に気にかけていると仮定すると、IntelのICCも試してみる必要があります。これは、GCCに勝る場合が多いため、Intelから30日間の評価ライセンスを取得できます。 comとそれを試してみてください。

于 2010-07-06T15:11:31.323 に答える
6

基本的に、答えは次のとおりです。それは状況によって異なります。さまざまな種類のアプリケーションに焦点を当てた多くのベンチマークがあります。

私のアプリケーションのベンチマークは、GCC> ICC >Clangです。

まれなI/Oがありますが、多くのCPUフロートおよびデータ構造操作があります。

コンパイルフラグは-Wall-g-DNDEBUG-O3です。

https://github.com/zhangyafeikimi/ml-pack/blob/master/gbdt/profile/benchmark

于 2014-04-08T12:19:24.507 に答える