NVIDIA CompileIQによる自動チューニングでカーネルパフォーマンスを最大化
NVIDIA は CUDA 13.3 に AI パワーによる自動チューニング機能「CompileIQ」を導入し、特定ワークロードに最適化されたコンパイラ設定を遺伝的アルゴリズムで発見する仕組みを提供した。
キーポイント
AI 駆動の自動チューニングフレームワークの実装
NVIDIA CompileIQ は、進化計算や遺伝的アルゴリズムを活用して、特定のワークロードに最適なコンパイラオプション(レジスタ割り当て、ループ展開など)を自動的に探索・決定する。
汎用最適化から特定ワークロード最適化への転換
従来のデフォルトヒューリスティクスは「幅広いワークロードで良い結果」を目指すものだが、CompileIQ は「特定のワークロードで最適な結果」を追求し、競合他社が手掛けるカスタムカーネル開発の難易度を下げる。
LLM 推論における計算リソースの集中化
現代の LLM 推論では、GEMM やアテンションカーネルが全体の 90% の計算量を占めるため、これらの小規模なコードセクションのわずかな最適化が全体のパフォーマンスに決定的な影響を与える。
計算リソースの集中と最適化の重要性
アテンション推論カーネルの約95%をFFN/MLPブロックのGEMMとアテンション変種が占めており、これらの小部分のコードに対するわずかな性能向上が、全体のパフォーマンスに大きな影響を与える。
CompileIQによる自動最適化
CompileIQは進化的・遺伝的アルゴリズムを用いて、レジスタ割り当てやループ変換など非公開の内部パラメータを探索し、ワークロードに特化したコンパイラ設定(ACF)を生成するAI駆動フレームワークである。
簡単な導入と実用化
pipコマンドで簡単にインストール可能であり、すでに主要なAIラボにおいて最もパフォーマンスが重要なワークロードの生産環境で使用されている。
自動設定とAPI連携
PTXASおよびNVCCのコンパイラ検索空間はAPIを介して自動的に取得され、手動ダウンロードや設定は不要です。
重要な引用
"finding the compiler options that unlock the best performance for a specific workload"
"'good across the board' and 'optimal for your workload' are two very different things."
"performance improvements in those code portions, even fractions of a percent, have outsized improvement"
CompileIQ flips the script, generating specialized compiler configurations tailored to each of your most critical kernels.
The team that hit a wall after exhausting every optimization lever they knew now has a new lever with CompileIQ—the compiler itself.
Your job as the developer is to define your objective function: for instance, a Python callable that takes a candidate compiler configuration, compiles your kernel with it, benchmarks the result, and returns a score.
影響分析・編集コメントを表示
影響分析
この技術は、AI インフラストラクチャ競争において、ハードウェア性能だけでなくソフトウェアスタックの微調整能力が重要視される現状を反映しており、開発者が手動で数週間かけて行っていた最適化プロセスを自動化・効率化する画期的な進展です。特に LLM 推論のような特定ワークロードに特化した環境では、コンパイラレベルでの最適化がスループット向上の最後の砦となるため、業界全体の開発生産性とパフォーマンス上限を引き上げる可能性があります。
編集コメント
コンパイラ設定を「ブラックボックス」から「AI が最適化するパラメータ」へと昇華させた点は、ハードウェア性能の限界に直面する現代の AI 開発において極めて重要な転換点です。
NVIDIA CompileIQ は、パフォーマンスエンジニアリングにおける最も困難な課題の一つに取り組んでいます。それは、特定のワークロードに対して最高のパフォーマンスを引き出すコンパイラオプションを見つけることです。
あるチームが、GPU 上で LLM の推論パイプラインを数週間かけて最適化し、バッチサイズの調整、FP8 への量子化、フラッシュアテンションの採用、可能な限りすべてのカーネルの融合を行ってきたと想像してください。プロファイラは、これ以上絞り込む余地がないと報告します。
しかし、コンパイラ自体をチューニング可能なパラメータに変えることはできないでしょうか?それが可能になりました。NVIDIA CUDA 13.3 のリリースには、CompileIQ が含まれています。これは、進化的アルゴリズムおよび遺伝的アルゴリズムを使用して、個々のワークロード向けに NVIDIA 汎用 GPU コンパイラを最適化する、AI パワー型のコンパイラ自動チューニングフレームワークです。
NVIDIA GPU コンパイラは、コンパイルするすべてのカーネルに対して、同じデフォルトのヒューリスティック(レジスタ割り当て戦略、命令スケジューリングの決定、ループ展開しきい値など)を適用します。これらのヒューリスティックは、広範なワークロードにわたって良好な結果を生み出すように設計されています。しかし、「全体的に良い」と「特定のワークロードに対して最適」は、非常に異なる概念です。
AI インフラにおける競争環境は、この格差を無視できなくしています。カスタム CUDA、Triton、および Helion カーネルを構築するチームは、スループットのあらゆるパーセントポイントのために努力しています。これまで、特定のワークロード向けにコード生成を微調整する方法はありませんでした。
90% の問題と機会
なぜコンパイラレベルの最適化がこれほど重要なのかを理解するには、現代の LLM(大規模言語モデル)推論において GPU 計算リソースが実際にどこに使われているかを考える必要があります。
アテンション推論カーネルでは、FFN/MLP ブロックの線形層における GEMM(行列乗算)と Q、K、V、および出力投影演算が、総 FLOPs の約 70% を占めます。スケーリングされたドットプロダクトアテンションや融合型・フラッシュアテンションのバリアントは、さらに 25% を占めています。これら 2 つのカーネルファミリーを合わせると、エンドツーエンドの推論計算量の 90% 以上を占めることになります。
これは AI 推論に特有のことではありません。多くのアプリケーションやアルゴリズムにおいて、計算時間の大部分がコードのごく一部で費やされており、つまりこれらの小さなコードセクションがアプリケーションのパフォーマンスに対して不釣り合いな大きな影響を与えています。このため、それらのコード部分におけるパフォーマンス向上—even 小数点以下のパーセントであっても—が、全体としてのアプリケーションパフォーマンスに不釣り合いなほどの改善をもたらします。
CompileIQ の紹介
CompileIQ は、進化的および遺伝的アルゴリズムを活用して、個々のワークロード向けに NVIDIA GPU コンパイラを最適化する AI 駆動のコンパイラ自動調整フレームワークです。すべてのワークロードに対して単一の汎用的なコンパイラ設定を受け入れるのではなく、CompileIQ はその発想を転換し、最も重要なカーネルそれぞれに合わせて特別化されたコンパイラ設定を生成します。
内部では、CompileIQ は公開されているコンパイラフラグからはアクセスできない豊富な内部コンパイラパラメータの空間を探査します。これにはレジスタ割り当て戦略、命令スケジューリングポリシー、ループ変換などが含まれます。その出力は、高度なコントロールファイル(ACF)であり、コンパイラはこのファイルを –apply-controls フラグを介して取り込みます。これにより、ワークロードに特化して最適化されたカーネルバイナリが生成されます。
こう考えてみてください:あなたのコンパイラには、すでにカーネル向けにより良いコードを生成する能力があります。ただ、どの内部設定の組み合わせがその結果をもたらすかを知っているだけではありません。CompileIQ の進化的探索は、その最適な組み合わせを自動的に見つけ出します。
これまで知っていたすべての最適化レバーを使い果たして壁にぶつかったチームにとって、CompileIQ は新たなレバー、つまりコンパイラそのものとなります。
CompileIQ は利用可能であり、次のセクションで示すように、pip を使用して好きな Python 環境にインストールできます。主要な AI ラボではすでに、パフォーマンスが最も重要なワークロードの生産環境でこれを利用しています。
4 つのステップで始める
CompileIQ はシンプルなワークフローを持つ Python パッケージです:
- Learn
- Install
- 目的を定義する
- 実行する
pip install compileiq
CompileIQ は、PTXAS および NVCC の両方に対応するコンパイラ探索空間を同梱しており、これらは API を介して自動的に取得されます。手動でのダウンロードや設定は不要です。
開発者としての役割は、目的関数を定義することです。例えば、候補となるコンパイラ構成を受け取り、それを用いてカーネルをコンパイルし、結果をベンチマークしてスコアを返す Python の呼び出し可能なオブジェクト(コール可能)などです。あなたのカーネルをベンチマークできるのであれば、CompileIQ を使用できます。
以下に例を示します:
import subprocess
from compileiq.ciq import Search
from compileiq.types import SearchConfiguration
def objective(config_blob):
with open("config.acf", "wb") as f:
f.write(bytes.fromhex(config_blob))
result = subprocess.run([
"ptxas", "-v", "-arch=sm_90a",
"--apply-controls", "config.acf",
"my_kernel.ptx"
], capture_output=True, text=True)
return extract_runtime(result.stdout)
config = SearchConfiguration(
pool_size=32, cull_size=24, generations=20,
mutate_rate=0.1, problem_type="min",
num_objectives=1
)
search = Search(config, objective)
best_acf = search.run()
上記のコードは、以下の 3 つの明確なセクションに分割できます:
- 目的を定義する:評価対象となる構成を config_blob として受け取り、ディスクに保存し、カーネルをコンパイル・実行してメトリクスを抽出する関数 objective を定義します。
- 検索の設定:1 回の生成で試す候補の数(pool_size)、実行する世代数、最適化する目的関数の数など、検索を駆動するパラメータを設定します。
- 検索を実行し、最良の候補を抽出します。
以上です。検索が開始されると、CompileIQ はコンパイラ構成の集団を初期化し、各構成を目的関数に対して評価し、最も優れたパフォーマンスを示すものを選択し、突然変異と交叉を適用して新しい候補を生成し、 successive generations(連続する世代)を経て最適な ACF に収束します。
「より良い」とはあなたのワークロードにとって何を意味するかは、目的関数で定義し、CompileIQ がそれを見つけます。
image*図 1. CompileIQ のワークフロー:目的の定義、初期化、評価、選択と突然変異、収束、デプロイ*
例
それでは、実際に試せる自己完結型の例に焦点を当てましょう。GitHub リポジトリには多数の例がありますが、ここでは 2 つを紹介します。まず、GPU コンピューティングとは無関係ですが、CompileIQ の使用原理を示す単一目的関数の例です。
from compileiq.ciq import Search
from compileiq.types import SearchConfiguration
import compileiq.search_spaces.base as ss
def objective(config):
score = config["x"] ** 2 + config["y"]
return score
def main():
dna_config = {
"x": ss.range(start=1.0, end=20.0, step=0.5),
"y": ss.choice([1, 2, 3]),
"z": ss.literal("this is a constant", knockout_prob=0.5),
}
main_config = SearchConfiguration(
generations=5,
problem_type="min",
num_objectives=1,
)
tuner = Search(
objective_function=objective,
search_space=dna_config,
search_config=main_config,
)
results = tuner.start()
print(f"Entire Results Dataframe:\n {results.get_results()}")
print(f"Best Result: {results.get_best_result()}")
if __name__ == "__main__":
main()
まず、目的関数(objective function)です:
def objective(config):
score = config["x"] ** 2 + config["y"]
return score
これは x を二乗し、その値を y に加算する単純な関数です。これが最適化する対象となる関数となります:
dna_config = {
"x": ss.range(start=1.0, end=20.0, step=0.5),
"y": ss.choice([1, 2, 3]),
"z": ss.literal("this is a constant", knockout_prob=0.5),
この設定(config)は、変数に許可される値を指定するものです。x の場合、範囲は 1.0 から 20.0 で、ステップサイズは 0.5 です。y の場合は、選択肢として 1、2、または 3 が選べます。z は実際には目的関数の計算には寄与しませんが、ドロップアウト(dropout)の例示として機能します。
main_config = SearchConfiguration(
generations=5,
problem_type="min",
num_objectives=1,
)
次に探索設定(search configuration)を指定します。このケースでは、5 世代(generations)を実行し、目的関数を最小化したいと考えており、分析される目的変数は 1 つのみです。
残りのコードは引数と探索の設定を行います。これは非常にシンプルな目的関数であり、手計算でも容易に算出できますが、説明のためにコードを実行した際の挙動を以下に示します。
$ python single_objective.py
🧬 Generation: 5/5|█| [elapsed: 00:00 · eta: 00:00] , 🏆 best_score=3.2500
Entire Results Dataframe:
metadata ... params
0 {"pid": 2562276} ... {'x': 2.5, 'y': 2, 'z': 'this is a constant'}
1 {"pid": 2562276} ... {'x': 8.5, 'y': 3}
2 {"pid": 2562276} ... {'x': 11.0, 'y': 1, 'z': 'this is a constant'}
3 {"pid": 2562276} ... {'x': 19.0, 'y': 2}
4 {"pid": 2562276} ... {'x': 13.5, 'y': 3}
.. ... ... ...
109 {"pid": 2562276} ... {'x': 1.5, 'y': 3, 'z': 'this is a constant'}
124 {"pid": 2562276} ... {'x': 1.0, 'y': 2, 'z': 'this is a constant'}
126 {"pid": 2562276} ... {'x': 2.0, 'y': 1, 'z': 'this is a constant'}
135 {"pid": 2562276} ... {'x': 3.0, 'y': 2, 'z': 'this is a constant'}
138 {"pid": 2562276} ... {'x': 1.5, 'y': 3}
[61 rows x 4 columns]
Best Result: {'metadata': '{"pid": 2562276}', 'generation': 4, 'score_1': 3.0, 'params': {'x': 1.0, 'y': 2, 'z': 'this is a constant'}}
最良の結果のリストには x = 1.0 および y = 2 が示されており、スコアは 3.0 となります。しかし、実際には x = 1.0 で y = 1 のときに最良のスコアが得られることを私たちは知っています。つまり、このケースでは CompileIQ は最良の答えを見つけられませんでした。世代数(今回の場合 5)が非常に少ないことと、探索の確率的な性質のため、絶対的な最良の答えにたまたま辿り着けなかっただけです。ただし、このケースで世代数をより大きな数値、例えば 15 に増やせば、ほぼ確実に最良の答えを得ることができます。
次に、特定のカーネルの GPU パフォーマンスを測定する例に移りましょう。GitHub リポジトリには、NVCC を使用してリダクションカーネルを構築する例があります。ここでは簡潔にするためコード全体は掲載せず、概念を説明するためのスニペットを示します。
検索を設定する Python 関数内では、以下のコードが使用されています:
search_space = args.search_space if args.search_space else NvccSearchSpace(version=cuda_version)
config = SearchConfiguration(
problem_type=ProblemType.MIN,
generations=args.generations,
pool_size=args.pool_size,
)
探索空間は、CUDA 13.3 に NvccSearchSpace を使用するように設定されています。また、最適化対象の目的関数のタイプが MIN(最小値)であることがわかります。これは、目的関数の最小値を見つけることを意味します。世代数とプールサイズはコマンドライン引数であり、この Python スクリプトではそれぞれデフォルトで 10 と 15 に設定されています。GPU カーネルコードは、リダクションを実行した後に実行時間を出力するようにセットアップされており、目的関数(ここではリストされていません)は本質的にカーネルをビルドして実行し、「Time = string」という文字列を検索します。これが探索空間全体で最小化される値です。
コンパイラ関連の nvcc_example フォルダにいると仮定すると、検索を実行した際の出力は以下のようになります。
$ python optimize_reduction.py --arch sm_120
Running baseline...
Baseline: 0.777 ms
Starting optimization (10 generations, pool=15)...
🧬 Generation: 10/10|█| [elapsed: 09:29 · eta: 00:00] , 🏆 best_score=0.7700, a
Baseline: 0.777 ms
Optimized: 0.770 ms
Speedup: 1.01x
Config saved: reduction_best_config.bin
Usage: nvcc --apply-controls reduction_best_config.bin -arch=sm_120 ...
検索によって発見された性能向上は約 1% ですが、この保存された設定を適用するには、生成した ACF(Auto-Tuning Configuration File)を追加し、--apply-controls オプションを使用するだけで済みます。
マルチ目的最適化と知的財産保護
ほとんどの自動調整ツールは、通常は実行時間という単一の指標を最適化対象としますが、CompileIQ はさらに一歩進んで、実行時間、コンパイル時間、消費電力といった競合する複数の目的間でのトレードオフを同時に探索する多目的最適化をサポートしています。
これは、「可能な限り最速」が常に正解とは限らないため重要です。電力制約のあるデータセンターでは、わずかな実行時間の増加を引き換えに大幅な電力削減を受け入れる場合があります。CI/CD パイプラインでは、反復サイクルを高速に保つためにコンパイル時間を優先するかもしれません。組み込み環境での展開では、これら 3 つの要素すべてをバランスさせる必要があるでしょう。
CompileIQ の進化エンジンにより、支配されない解、つまりある目的を改善すると別の目的が悪化するような構成が存在しない状態のパレートフロンティア Pareto frontier が計算されます。チームは、単一の最適化軸に縛られるのではなく、自社の制約条件に合ったトレードオフを選択できます。
この機能により、CompileIQ の適用範囲は LLM 推論のみに限定されず、NVIDIA コンパイラが利用されるあらゆる分野——科学技術計算、自動運転車、画像処理、推薦システムなど——において、デフォルトのヒューリスティックでは見逃してしまうような最適化空間を探索し、最適な構成を提示することが可能になります。
IP保護の観点から、CompileIQは双方が安全に保たれるように設計されています。コンパイラの内部構造は探索空間とACF(応答特性関数)内にカプセル化され、ユーザーがコンパイラのパラメータを気にする必要はありません。ユーザーのワークロードは常に独自の環境内に留まり、目的関数はローカルで実行され、生成されるのは結果としてのACFのみです。ACFはバージョン管理に安全にコミットでき、チーム間でも共有可能です。
image*図 2. 3D パレートフロンティア:実行時間 vs コンパイル時間 vs 消費電力*
結果と本番環境での採用
CompileIQは、GPUおよびCPUターゲットにおける本番ワークロードで検証済みです。例えば、このGTC トークでは、TritonBench および Helion カーネルにおいて最大 15% のパフォーマンス向上を示しています。
これらの改善は、著者によって「完了」と見なされていたカーネルのすでに最適化されたベースラインの上に達成されたものです。この改善は、デフォルトのヒューリスティックでは決して選択されないコンパイラ構成を CompileIQ が発見した直接的な結果です。
主要な AI ラボでは、すでに CompileIQ を本番環境で使用しており、パフォーマンスが最も重要な推論およびトレーニングワークロードに活用されています。同ツールが生成する ACF は完全に再現可能で移植可能です:同じベンチマークと基盤となるコンパイラが一致している限り、同じ ACF がデプロイ先を超えて最適化されたバイナリを生成します。チームは、ACF をカーネルソースコードとともにバージョン管理システムにコミットし、コンパイラの最適化を開発ワークフローにおけるバージョン管理され、レビュー可能な一部として位置づけています。
あなたの番です
PTXAS および NVCC の両方に対して、コンパイラ探索空間が利用可能です。最も影響の大きいカーネルを特定し(GEMM とアテンションが最良の候補となります)、ワークロードにとって重要な指標を測定するベンチマークを作成して CompileIQ を実行してください。
ドキュメント、API リファレンス、および有用な例は、CompileIQ の ドキュメント サイトで確認できます。ご質問やサポートについては、CompileIQ GitHub リポジトリにイシューを登録してください。
明確にしておくべき点があります:CompileIQ は、書き込まれたコードが不十分でも自動的に高性能なコードに変換する魔法のようなツールではありません。CompileIQ から最大の価値を引き出すには、まず比較的パフォーマンスの高いコードから始める必要があります。それによって、最終的なコンパイラのヒューリスティックによる微調整が可能となり、最大のパフォーマンスへと導くことができます。
ただし、チームが知っているすべての最適化レバーを使い果たしている場合でも、CompileIQ は新たなレバーを提供します——それはコンパイラそのものです。
CompileIQ をダウンロードし、GitHub の例を確認して、今日からカーネルの最適化を開始してください*。
必ず JSON 形式で返してください。translation フィールドのみ。他のフィールド (technical_terms 等) は一切追加しないこと — 余計なフィールドを書こうとして本文翻訳がトークン上限で打ち切られる事故を防ぐため:
{"translation": "翻訳全文"}
原文を表示
NVIDIA CompileIQ tackles one of the hardest problems in performance engineering: finding the compiler options that unlock the best performance for a specific workload.
Consider a team that has spent weeks optimizing an LLM inference pipeline on GPUs, tuning batch sizes, quantizing to FP8, adopting flash attention, fusing every kernel they can. The profiler says there’s nothing left to squeeze.
But what if you could turn the compiler itself into a tunable parameter? Now you can. The release of NVIDIA CUDA 13.3 includes CompileIQ, an AI-powered compiler auto-tuning framework that uses evolutionary and genetic algorithms to optimize NVIDIA general purpose GPU compilers for individual workloads.
NVIDIA GPU compilers apply the same default heuristics (register allocation strategies, instruction scheduling decisions, loop unrolling thresholds, etc.) to every kernel they compile. These heuristics are engineered to produce good results across a vast range of workloads. But “good across the board” and “optimal for your workload” are two very different things.
The competitive landscape in AI infrastructure has made this gap impossible to ignore. Teams building custom CUDA, Triton, and Helion kernels are striving for every percentage point of throughput. Until now, there hasn’t been a way to fine-tune code generation for a specific workload.
The 90% problem and the opportunity
To understand why compiler-level optimization matters so much, consider where GPU compute actually goes in modern LLM inference.
In attention inference kernels, GEMMs in the linear layers of FFN/MLP blocks plus the Q, K, V, and output projections account for approximately 70% of total FLOPs. Scaled dot-product attention, fused and flash attention variants account for another 25%. Together, these two kernel families represent more than 90% of end-to-end inference compute.
This is not unique to AI inference. There are many applications and algorithms where a large portion of the compute time is spent in relatively small portions of the code, which means these small code sections contribute an outsized influence to the performance of the application. Because of this, performance improvements in those code portions, even fractions of a percent, have outsized improvements on overall application performance.
Introducing CompileIQ
CompileIQ is an AI-powered compiler auto-tuning framework that uses evolutionary and genetic algorithms to optimize NVIDIA GPU compilers for individual workloads. Instead of accepting one generic compiler configuration for all workloads, CompileIQ flips the script, generating specialized compiler configurations tailored to each of your most critical kernels.
Under the hood, CompileIQ explores a rich space of internal compiler parameters that aren’t exposed through any public compiler flag: register allocation strategies, instruction scheduling policies, loop transformations, and more. The output is an advanced controls file (ACF) that the compiler ingests via the –apply-controls flag, producing a kernel binary optimized specifically for your workload.
Think of it this way: Your compiler already has the capability to generate better code for your kernel. It just doesn’t know which combination of internal settings will get there. CompileIQ’s evolutionary search finds that combination automatically.
The team that hit a wall after exhausting every optimization lever they knew now has a new lever with CompileIQ—the compiler itself.
CompileIQ is available and can be installed into your favorite Python environment using pip, as shown in the next section. Leading AI labs are already using it in production for their most performance-critical workloads.
Getting started in 4 steps
CompileIQ is a Python package with a simple workflow:
- Learn
- Install
- Define your objective
- Run
pip install compileiq
CompileIQ ships with compiler search spaces for both PTXAS and NVCC that are automatically fetched via APIs. No manual downloads or configuration are required.
Your job as the developer is to define your objective function: for instance, a Python callable that takes a candidate compiler configuration, compiles your kernel with it, benchmarks the result, and returns a score. If you can benchmark your kernel, you can use CompileIQ.
Here’s an example:
import subprocess
from compileiq.ciq import Search
from compileiq.types import SearchConfiguration
def objective(config_blob):
with open("config.acf", "wb") as f:
f.write(bytes.fromhex(config_blob))
result = subprocess.run([
"ptxas", "-v", "-arch=sm_90a",
"--apply-controls", "config.acf",
"my_kernel.ptx"
], capture_output=True, text=True)
return extract_runtime(result.stdout)
config = SearchConfiguration(
pool_size=32, cull_size=24, generations=20,
mutate_rate=0.1, problem_type="min",
num_objectives=1
)
search = Search(config, objective)
best_acf = search.run()
The code above can be separated into three distinct sections:
- Define your objective: We define the function objective, which takes the configuration to be evaluated in config_blob, saves it to disk, compiles and runs the kernel, and then extracts the metric.
- Configure the search: Set the parameters that will drive the search, like how many candidates to try in one generation (pool_size), how many generations to run, and the number of objectives to be optimized.
- Run the search and extract the best candidate.
That’s it. When the search starts, CompileIQ initializes a population of compiler configurations, evaluates each one against your objective function, selects the best performers, applies mutation and crossover to generate new candidates, and converges on an optimal ACF over successive generations.
You define what “better” means for your workload in the objective function, and CompileIQ finds it.

Examples
Now let’s focus on self-contained examples that you can try. There are a number of examples in the GitHub repo, and we’ll demonstrate two here. First, the single objective example, which has nothing to do with GPU computing, but demonstrates the principles of using CompileIQ.
from compileiq.ciq import Search
from compileiq.types import SearchConfiguration
import compileiq.search_spaces.base as ss
def objective(config):
score = config["x"] ** 2 + config["y"]
return score
def main():
dna_config = {
"x": ss.range(start=1.0, end=20.0, step=0.5),
"y": ss.choice([1, 2, 3]),
"z": ss.literal("this is a constant", knockout_prob=0.5),
}
main_config = SearchConfiguration(
generations=5,
problem_type="min",
num_objectives=1,
)
tuner = Search(
objective_function=objective,
search_space=dna_config,
search_config=main_config,
)
results = tuner.start()
print(f"Entire Results Dataframe:\n {results.get_results()}")
print(f"Best Result: {results.get_best_result()}")
if __name__ == "__main__":
main()
First, the objective function:
def objective(config):
score = config["x"] ** 2 + config["y"]
return score
This is a simple function that squares x, and adds that value to y. This is the function we’ll optimize:
dna_config = {
"x": ss.range(start=1.0, end=20.0, step=0.5),
"y": ss.choice([1, 2, 3]),
"z": ss.literal("this is a constant", knockout_prob=0.5),
The config specifies what values are permitted for the variables. For x, the range is between 1.0 and 20.0, with step size of 0.5. For y, the choices are either 1, 2 or 3; z doesn’t actually contribute to the calculation of the objective, but illustrates dropout.
main_config = SearchConfiguration(
generations=5,
problem_type="min",
num_objectives=1,
)
Next we specify the search configuration. In this case we’ll run 5 generations, we want to minimize the objective function, and there is only one objective being analyzed.
The rest of the code sets up the arguments and the search. This is a very simple objective function and you can calculate it by hand easily, but for illustrative purposes here’s what happens when you run the code.
$ python single_objective.py
🧬 Generation: 5/5|█| [elapsed: 00:00 · eta: 00:00] , 🏆 best_score=3.2500
Entire Results Dataframe:
metadata ... params
0 {"pid": 2562276} ... {'x': 2.5, 'y': 2, 'z': 'this is a constant'}
1 {"pid": 2562276} ... {'x': 8.5, 'y': 3}
2 {"pid": 2562276} ... {'x': 11.0, 'y': 1, 'z': 'this is a constant'}
3 {"pid": 2562276} ... {'x': 19.0, 'y': 2}
4 {"pid": 2562276} ... {'x': 13.5, 'y': 3}
.. ... ... ...
109 {"pid": 2562276} ... {'x': 1.5, 'y': 3, 'z': 'this is a constant'}
124 {"pid": 2562276} ... {'x': 1.0, 'y': 2, 'z': 'this is a constant'}
126 {"pid": 2562276} ... {'x': 2.0, 'y': 1, 'z': 'this is a constant'}
135 {"pid": 2562276} ... {'x': 3.0, 'y': 2, 'z': 'this is a constant'}
138 {"pid": 2562276} ... {'x': 1.5, 'y': 3}
[61 rows x 4 columns]
Best Result: {'metadata': '{"pid": 2562276}', 'generation': 4, 'score_1': 3.0, 'params': {'x': 1.0, 'y': 2, 'z': 'this is a constant'}}Notice the listing of the best result has x = 1.0 and y = 2, which results in a score of 3.0. But we know the best score is actually when x = 1.0 and y = 1, so in this case CompileIQ didn’t find the best answer. Due to the very low number of generations (in our case 5) and the stochastic nature of the search, we didn’t happen to find the absolute best answer. However, in this case if you increase the generation to a larger number, say 15, you will almost always obtain the best answer.
Let’s move to an example that measures GPU performance of a specific kernel. In the GitHub repo there is an example using NVCC to build a reduction kernel. We won’t include the entire code here for brevity, but will show snippets to illustrate the concepts.
In the Python function which sets up the search, we have this code:
search_space = args.search_space if args.search_space else NvccSearchSpace(version=cuda_version)
config = SearchConfiguration(
problem_type=ProblemType.MIN,
generations=args.generations,
pool_size=args.pool_size,
)
The search space is configured to use the NvccSearchSpace for CUDA 13.3. And you can see the problem type to optimize for is MIN, which means we want to find the minimum of the objective function. Generations and pool size are command line arguments which default to 10 and 15 respectively in this Python script. The GPU kernel code is set up to run a reduction and then print out the time, and the objective function (not listed here) essentially builds and runs the kernel, and searches for the Time = string and this is the value that is minimized over the search space.
Assuming you’re in the compilers/nvcc_example folder, here’s what it looks like when you run the search.
$ python optimize_reduction.py --arch sm_120
Running baseline...
Baseline: 0.777 ms
Starting optimization (10 generations, pool=15)...
🧬 Generation: 10/10|█| [elapsed: 09:29 · eta: 00:00] , 🏆 best_score=0.7700, a
Baseline: 0.777 ms
Optimized: 0.770 ms
Speedup: 1.01x
Config saved: reduction_best_config.bin
Usage: nvcc --apply-controls reduction_best_config.bin -arch=sm_120 ...The performance increase found via the search is roughly 1%, and you can see that to apply this saved configuration you just need to use the –-apply-controls option and add the ACF that you just generated.
Multi-objective optimization and IP protection
Most auto-tuning tools optimize for a single metric, typically runtime. CompileIQ goes further, supporting multi-objective optimization, simultaneously exploring trade-offs across competing objectives like runtime, compile time, and power consumption.
This matters because “fastest possible” isn’t always the right answer. A power-constrained datacenter might accept a marginal runtime increase in exchange for significantly lower power draw. A CI/CD pipeline might prioritize compile time to keep iteration cycles fast. An embedded deployment might need to balance all three.
CompileIQ’s evolutionary engine computes a Pareto frontier of non-dominated solutions, or configurations where no single objective can be improved without worsening another. Your team picks the trade-off that fits your constraints, rather than being locked into a single optimization axis.
This capability extends CompileIQ’s applicability well beyond LLM inference. Anywhere NVIDIA compilers are used—scientific computing, autonomous vehicles, image processing, recommendation systems—CompileIQ can explore the optimization space and surface configurations that default heuristics miss.
On the IP protection front, CompileIQ is designed so that both sides stay secure. Compiler internals remain encapsulated within the search space and ACFs. Users need not concern themselves with compiler parameters. User workloads never leave their own environment; the objective function runs locally, and only the resulting ACF is produced. ACFs are safe to commit to version control and share across teams.

Results and production adoption
CompileIQ has been validated across GPU and CPU targets on production workloads. For example, this GTC talk shows results of up to 15% performance improvement on both TritonBench and Helion kernels.
These gains come on top of already-optimized baselines in kernels that were considered “done” by their authors. The improvements are the direct result of CompileIQ discovering compiler configurations that the default heuristics would never select.
Leading AI labs are already using CompileIQ in production for their most performance-critical inference and training workloads. The ACFs it produces are fully reproducible and portable: the same ACF generates the same optimized binary across deployments as long as the same benchmark and underlying compiler are matching. Teams commit ACFs to version control alongside their kernel source code, making compiler optimization a versioned, reviewable part of the development workflow.
Your turn
Compiler search spaces are available for both PTXAS and NVCC. Identify your highest-impact kernels – GEMM and attention are the best candidates – write a benchmark that measures what matters to your workload, and run CompileIQ.
Documentation, API reference, and useful examples are available at the CompileIQ documentation site. For questions and support, file an issue on the CompileIQ GitHubrepository.
One thing we should be clear on: CompileIQ is not a magic tool that automatically turns poorly-written code into high-performing code. To get the best value from CompileIQ, you need to start with reasonably high-performing code, which then enables the final compiler-heuristics tweaks to take you to maximum performance.
But, if your team has exhausted every optimization lever they know of, CompileIQ gives them a new lever—the compiler itself.
Download CompileIQ, check out the examples in GitHub, and start optimizing your kernels today*.*
関連記事
今日のまとめ
AI日報で今日の重要ニュースをまとめ読み