ホストマシン(linux x86)とターゲットマシン(arm)で実行されるc++で小さなアプリケーションを作成しています。
私が抱えている問題は、ホストマシンではバイナリのサイズが約700kbですが、ターゲットマシンでは約7mbであるということです。
両方のプラットフォームで同じコンパイルスイッチを使用しています。私の最初は、argetマシン上のライブラリが静的にリンクされたということでしたが、両方のバイナリをチェックしobjdump
、両方が同じ動的リンクライブラリを使用しています。では、なぜこのようにサイズに大きな違いがあるのかを理解する方法を教えてもらえますか?
4 に答える
コンピュータアーキテクチャが異なれば、理論的には同じプログラムに対して完全に異なる量の実行可能コードが必要になる可能性がありますが、最近のアーキテクチャでは10倍は実際には期待されていません。ARMとx86は異なる場合がありますが、メモリと帯域幅が無駄にならない同じユニバースで設計されているため、CPU設計者は実行可能コードを可能な限りタイトに保つように努めています。
したがって、確率の順に、次の可能性を検討します。
シンボルストリッピング:2つのバイナリの1つがシンボルからストリッピングされている場合、特にデバッグ情報を使用してコンパイルすると、大幅に小さくなります。両方のバイナリを削除して、何が起こるかを確認することをお勧めします。
静的リンク:共有ライブラリを使用するよりも静的リンクを優先する組み込みターゲットのビルドシステムに遭遇することがあります。各バイナリのライブラリ依存関係を調べると、おそらくこれが検出されます。
追加の有効なコード:ビルドシステムが追加のオプションのライブラリを検出したため、またはターゲットプラットフォームに特定のハンドルが必要なため、より大きなバイナリで追加のコードが有効になっている可能性があります。
それでも、小さいバイナリに多くの機能が欠けているか、大きいバイナリがオプションのライブラリに静的にリンクされていない限り、10の係数はおそらくこれには多すぎます。
異なるコンパイラ構成:提供するコンパイラオプションだけでなく、コンパイラが各ターゲットに使用するデフォルトも確認する必要があります。たとえば、コンパイラが1つのアーキテクチャで大幅に高いインライン化またはループ展開の制限を持っている場合、結果の実行可能ファイルは著しくバロンアウトする可能性があります。
まず、異なるアーキテクチャ用にコンパイルされた同じコードが互いにサイズの関係を持っていると期待する理由はありません。AをBより大きくして、コードを1行変更すると、BをAより大きくすることができます。
第二に、あなたが話している「バイナリ」は、私が推測しているエルフです。これは、少しのバイナリであり、いくつかのオーバーヘッドがあります。オーバーヘッドは、アーキテクチャと他のそのようなものの間で異なる可能性があります。
結論として、2つのアーキテクチャ/プラットフォーム用に同じコードをコンパイルする場合、または同じアーキテクチャ用に異なるコンパイラまたはコンパイルオプションを使用する場合、ファイルサイズが相互に関係することを期待する理由はありません。
アーキテクチャが異なれば、同じことを処理する方法もまったく異なります。たとえば、CISC(x86など)アーキテクチャでの即時値のロードは通常1つの命令ですが、RISC(ppc、armなど)では通常複数の命令であり、実際に必要な数は値によって異なります。たとえば、命令セットで16ビットの即値のみが許可されている場合、64ビット値をロードするために最大7つの命令が必要になる場合があります(16ビットによるロードとロード間のシフト)。したがって、コードは本質的に異なります。
これまで言及されていませんが、ARM / x86の比較に関連する理由の1つは、浮動小数点エミュレーションです。現在、すべてのx86チップにはネイティブFPサポートが付属しています(SSEを介したSIMD FPサポートがある場合でもx86-64)が、ARMCPUにはFPユニットがないことがよくあります。つまり、単純なFP加算でさえ、指数と仮数に対する整数演算の長いシーケンスに変換する必要があります。