Linux コンパイル最適化で習得しなければならないいくつかの姿勢のまとめ

Linux コンパイル最適化で習得しなければならないいくつかの姿勢のまとめ

01. コンパイルオプションとカーネルコンパイル

Linux カーネル (英語: linux kernel) は、POSIX 標準に準拠し、C 言語とアセンブリ言語で記述され、GNU General Public License に基づいてリリースされているコンピュータ オペレーティング システム カーネルです。技術的に言えば、Linux は単なるカーネルです。 「カーネル」とは、ハードウェア抽象化レイヤー、ディスクおよびファイルの制御、マルチタスクなどの機能を提供するシステム ソフトウェアを指します。

まず、Linux カーネルが O0 でコンパイルされている場合はコンパイルできないことは誰もが知っています。Linux カーネルは O2 または Os でコンパイルされます。これは Linux Makefile から確認できます。

選択すると

CONFIG_CC_OPTIMIZE_FOR_SIZE

Os になります。それ以外の場合は O2 になります。

実際、O2 と Os はいくつかの最適化オプションの集合です。

gcc -c -Q -O2 --help=オプティマイザ > /tmp/O2-opts

gcc -c -Q -Os --help=オプティマイザ > /tmp/Os-opts

前者は速度の最適化に基づく傾向があり、後者はより小さなサイズの最適化に基づく傾向があります。 2 つのスイッチ オプションを比較します。

/tmp/O2-opts /tmp/Os-optsをマージする

その差は悲しいほど小さいです:

O2 と Os はどちらもインラインの小さな関数と一度だけ呼び出される関数を有効にしますが、-finline-functions は O2 では無効になっており、Os では有効になっています。 O2 では optimize-strlen はオンですが、Os ではこのオプションはオフになっています。関連するオプションの意味は、「man gcc」で確認できます (質問がある場合は、man を検索してください)。たとえば、man gcc の後に inline-functions を検索すると次のようになります。

O0 から O1、O2、O3 へと、有効にする最適化オプションの数を徐々に増やしていくプロセスです。

カーネル自体は O0 でコンパイルするように設計されていないため、カーネルを O0 でコンパイルすることはできません。カーネルの設計には、コンパイルが最適化されるという前提が含まれています。これを説明するために簡単な例を使ってみましょう。

02. 簡単な例

次のコード:

O0 コンパイルでは、f() 関数が定義されていないという次のエラーが報告されます。

$ gcc -O0 cc.c

cc.c:1:13: 警告: 'f' が使用されていますが、定義されていません [デフォルトで有効]

 void f(void);

    ^

/tmp/ccTwwtHG.o: 関数 `main' 内:

cc.c:(.text+0x19): `f' への未定義の参照

collect2: エラー: ld が 1 終了ステータスを返しました

しかし、O2 でコンパイルすると、問題は発生しません。

$ gcc -O2 cc.c

その理由は、O2 がコンパイルされると、a == 1 であることが認識されるため、if (a>2) は成立せず、f() が定義されていなくても問題にならないからです。

コードを少し変更した後:

O2は現在動作していません:

$ gcc -O2 cc.c

/tmp/ccXiyBHn.o: 関数 `main' 内:

cc.c:(.text.startup+0x7): `f' への未定義の参照

collect2: エラー: ld が 1 終了ステータスを返しました

したがって、この例から、同じコードが O2 では合格できるのに O0 では合格できない理由がわかります。カーネルには、コンパイラによって最適化されるはずのコードが多数あります。

3. もうインライン化したくない

コンパイルの最適化により、一部の関数(小さな関数やプロジェクト全体で 1 人だけが呼び出す関数など)は明示的にインラインとして記述されていないにもかかわらず、コンパイラによってインラインに最適化されます。この関数に対応するシンボルが見つからないため、デバッグ時に問題が発生します。

この時点で、特定の関数をインライン化したくないことを明示的に指定できます。

そうでない場合、O2 と Os は関連するインライン オプションを有効にするため、コードに inline を記述していなくても、上記 2 つの関数はコンパイラによって自動的にインライン化される可能性があります。インライン化を拒否する場合は、noline でマークできます。

4. 最適化されたくない

O1、O2、O3、および Os がグローバルに有効になっている場合、単一の関数に対して最適化を実行したくない場合は、 __attribute__((optimize("O0")))を使用して関数を変更できます。たとえば、O2 でコンパイルできる上記のコードを次のように変更します。

O2で再コンパイル:

$ gcc -O2 cc.c

/tmp/cc8M338p.o: 関数 `main' 内:

cc.c:(.text+0x19): `f' への未定義の参照

collect2: エラー: ld が 1 終了ステータスを返しました

5. 結論

以下に実用的なガイドラインをいくつか示します。

  1. O0 でカーネルをコンパイルしないようにしてください。これは実際のエンジニアリングの実践に沿わず、主流の Linux コミュニティによって十分にサポートされていません。カーネルは、さらなる最適化のために O2/Os に依存しています。
  2. O2 でコードが正しいことを追求し、コードはコンパイラの最適化に耐える必要があります。たとえば、O0 は正常に動作するが O2 は動作しない場合は、自分で原因を見つけてアセンブリを分析する必要があります。
  3. グローバル最適化中に特定の部分の最適化を回避したい場合は、noinline、__attribute__((optimize("O0"))) などを使用して、外科的な調整を試みることができます。

要約する

上記はこの記事の全内容です。この記事の内容が皆さんの勉強や仕事に一定の参考学習価値を持つことを願っています。ご質問があれば、メッセージを残してコミュニケーションしてください。123WORDPRESS.COM を応援していただきありがとうございます。

以下もご興味があるかもしれません:
  • Linux で unzip コマンドを使用して複数のファイルを解凍する方法
  • 知っておくべき Linux コマンド スキル 30 選
  • Linux でプロセスを隠す方法と、遭遇する落とし穴
  • Linuxコマンドheadとtailの一般的な使用法の詳細な説明
  • sudo、su、su の違いのまとめ - Linux のコマンド
  • Linuxで実行中のプロセスを素早く見つける方法

<<:  JSはカード配布アニメーションを実現します

>>:  MySQL 5.7.17 winx64 無料インストールバージョン設定方法グラフィックチュートリアル

推薦する

Baota LinuxパネルにFTP接続できない問題の解決方法の詳細な説明

Alibaba Cloud Server を使用している場合は、セキュリティ グループ設定でポート ...

Vueコンポーネント通信のさまざまな方法の詳細な説明

目次1. 父から息子へ2. 息子から父へ3. 親子関係のないコンポーネントの値の転送4. ヴュークス...

react+reduxを使用してカウンター機能を実装すると発生する問題

Redux はシンプルな状態マネージャーです。その歴史をたどることはしません。使用法の観点から見ると...

MySQLの文字セット設定を5分で理解しましょう

目次1. コンテンツの概要2. 文字セットと文字順序の概念と関係3. MySQL でサポートされてい...

Dockerにlogstashをインストールする詳細な手順

docker-compose.yml を編集し、次のコンテンツを追加します。 バージョン: '...

さまざまなマウスの形状を表現する方法

<a href = "http://" style = "cur...

MySQL 8.0 のデフォルトのデータディレクトリを変更する (設定なしの簡単な操作)

使用シナリオ: Alibaba Cloud を使用しており、データディスクを別途購入しました (大容...

Windows 環境に mysql-8.0.11-winx64 をインストールする際に発生する問題を解決する

MySQL インストール パッケージをダウンロードします。mysql-8.0.11-winx64 を...

JavaScript が Jingdong の虫眼鏡の特殊効果を模倣

この記事では、Jingdong虫眼鏡を模倣したJavaScriptの具体的なコードを参考までに共有し...

nginx ウェブサイト サービスのアンチホットリンクを設定する方法 (推奨)

1. ホットリンクの原則1.1 Webページの準備Web ソース ホスト (192.168.153...

Vue3はJingdong製品詳細ページの虫眼鏡効果コンポーネントをカプセル化します

この記事では、Jingdong製品詳細ページの虫眼鏡効果コンポーネントに似たvue3カプセル化の具体...

html2canvas で破線境界線を実装する例

html2canvas は、HTML 要素からキャンバスを生成するライブラリです。描画されるキャンバ...

IE8互換表示(IE7モード)とスタンドアロンIE7の違いの詳細な説明

1つ。 IE8 互換表示の概要<br />新しいバージョンのブラウザが古い Web サイ...

シンプルなショッピングカートの最も完全なコード分析を実装する JavaScript (ES6 オブジェクト指向)

この記事では、シンプルなショッピングカートを実装するためのJavaScriptの具体的なコードを参考...

Antdesign-vueとsortablejsを組み合わせて、2つのテーブルをドラッグして並べ替える機能を実現

目次成果を達成するsortablejs の紹介具体的な実装成果を達成する最初は、antdesign ...