web-dev-qa-db-ja.com

なぜアセンブリでプログラムするのですか?

私はそこにいるすべての筋金入りの低レベルのハッカーに質問があります。ブログでこの文を見つけました。ソースは重要だとは思いません(本当に気にするならHaackです)。

たとえば、最新の3Dゲームの多くには、C++およびアセンブリで記述された高性能コアエンジンがあります。

アセンブリに関する限り-コンパイラに余分な命令を出力させたり、過剰なバイトを使用したりしたくないため、またはCで表現できない(またはそれなしでは表現できない優れたアルゴリズムを使用しているため)コンパイラはそれらをいじります)?

低レベルのものを理解することが重要だと完全に理解しています。あなたがそれを理解した後、私はアセンブリのwhyプログラムを理解したいだけです。

85
Tom Ritter

あなたはこの声明を誤解していると思います:

たとえば、最新の3Dゲームの多くには、C++およびアセンブリで記述された高性能コアエンジンがあります。

ゲーム(および最近のほとんどのプログラム)は、「C++で書かれた」のと同じように「アセンブリで書かれた」わけではありません。このブログは、ゲームの大部分がAssemblyで設計されていることや、プログラマーのチームが主要言語としてAssemblyで開発していることを言っているのではありません。

これがreallyの意味するところは、開発者が最初にゲームを記述し、C++で動作させることです。次に、彼らはそれをプロファイルし、ボトルネックが何であるかを理解し、それが価値がある場合、彼らはアセンブリでそれらから一体を最適化します。または、既に経験している場合、どの部分がボトルネックになるかを知っており、構築した他のゲームの最適化された部分を用意しています。

Assemblyでのプログラミングのpointは、以前と同じです:speed。アセンブラでlotのコードを記述するのはばかげていますが、コンパイラが認識していない最適化がいくつかあり、コードのウィンドウが十分に小さい場合は、人間がよりうまくやるでしょう。

たとえば、浮動小数点の場合、コンパイラはかなり保守的である傾向があり、アーキテクチャのより高度な機能の一部を認識しない場合があります。エラーを受け入れても構わないのであれば、通常はコンパイラよりも良い結果が得られます。アセンブリに多くの時間を費やしていることがわかった場合は、アセンブリでそのコードを少し書く価値があります。

関連する例をいくつか示します。

ゲームの例

  • Intelの記事 SSE組み込み関数を使用したゲームエンジンの最適化について。最終コードでは組み込み関数(インラインアセンブラではない)を使用しているため、純粋なアセンブリしかし、彼らはコンパイラが出力するアセンブラを見て、最適化するものを正確に見つけ出します。

  • Quakeの 高速逆平方根 。繰り返しますが、ルーチンにはアセンブラーは含まれていませんが、この種の最適化を行うには、アーキテクチャーについて何かを知る必要があります。著者は、どの演算が高速(乗算、シフト)および低速(除算、sqrt)であるかを知っています。そのため、遅い演算を完全に回避する平方根の非常にトリッキーな実装を考え出します。

高性能コンピューティング

  • ゲームの領域外では、科学計算の人々は頻繁に物事のくだらない部分を最適化して、最新のハードウェアで高速に実行できるようにします。これは、物理学をごまかすことができないゲームと考えてください。

    これの素晴らしい最近の例は、 Lattice Quantum Chromodynamics(Lattice QCD) です。 このペーパー は、問題が1つの非常に小さな計算カーネルに要約される方法を説明します。これは、 IBM Blue Gene/L上のPowerPC 440用に大きく最適化されました。 。各440には2つのFPUがあり、コンパイラーが利用しにくい特殊な3項演算をサポートしています。これらの最適化がなければ、ラティスQCDの実行はずっと遅くなり、高価なマシンで何百万ものCPU時間を必要とする場合にはコストがかかります。

    whyこれが重要だと思っているなら、この作品から出てきた Science in Article をチェックしてください。ラティスQCDを使用して、これらの人たちは第一原理から陽子の質量を計算し、昨年は質量の90%が強い力の結合エネルギーに由来し、残りがクォークに由来することを示しました。それは E = mc2 アクション中。 概要を示します

上記のすべてについて、アプリケーションはnotアセンブリで100%設計または記述されており、近くさえありません。しかし、人々が本当に速度を必要とするとき、彼らは特定のハードウェアで飛ぶためにコードの重要な部分を書くことに集中します。

166
Todd Gamblin

私は長年アセンブリ言語でコーディングしていませんが、よく見たいくつかの理由を説明できます。

  • すべてのコンパイラが特定のCPU最適化と命令セット(たとえば、Intelが時々追加する新しい命令セット)を利用できるわけではありません。コンパイラの作成者が追いつくのを待つことは、競争上の優位性を失うことを意味します。

  • 実際のコードを既知のCPUアーキテクチャと最適化に簡単に一致させます。たとえば、フェッチメカニズム、キャッシュなどについて知っていること。これは開発者には透過的であるはずですが、実際はそうではないため、コンパイラライターは最適化できます。

  • 特定のハードウェアレベルのアクセスは、アセンブリ言語を介してのみ可能/実用的です(たとえば、デバイスドライバーの作成時)。

  • 正式な推論は、コードの最終またはほぼ最終的なレイアウトが既にわかっているため、実際にはアセンブリ言語の方が高水準言語よりも簡単な場合があります。

  • APIが存在しない特定の3Dグラフィックカード(1990年代後半)のプログラミングは、アセンブリ言語ではより実用的かつ効率的であり、他の言語では不可能な場合がありました。しかし、これもまた、特定の順序でデータを手動で出し入れするようなアクセラレータアーキテクチャに基づいた、本当にエキスパートレベルのゲームに関係していました。

アセンブリ言語は、特にその言語がC言語である場合に、高レベルの言語が使用する場合に多くの人が使用することを疑います。大量の汎用コードを手動で最適化するのは非現実的です。

42
Uri

アセンブラープログラミングには、他の人が言及していない側面が1つあります。アプリケーション内のすべてのバイトがコンパイラーではなく、ユーザー自身の努力の結果であることを知って満足感を得ることができます。 80年代前半に行っていたように、アセンブラーでアプリ全体を作成することに二度と戻りたくはありませんが、時々その感覚が恋しいです...

19
anon

通常、素人のアセンブリはC(Cの最適化のため)よりも遅いですが、多くのゲーム(明確に Doom )がアセンブリにゲームの特定のセクションを持たなければならなかったため、通常のマシンでスムーズに動作します。

これが私が参照している例です

16
Ólafur Waage

私は最初の仕事(80年代)でアセンブリ言語でプロのプログラミングを始めました。組み込みシステムの場合、メモリ要求-RAMおよびEPROM-)は低かった。リソース上で簡単なタイトなコードを書くことができた。

80年代後半までに、私はCに切り替えました。コードの記述、デバッグ、保守が簡単になりました。非常に小さなコードのスニペットがアセンブラーで書かれていました-私にとっては、ロールユア独自のRTOSでコンテキストスイッチングを書いていたときでした。 (「科学プロジェクト」でない限り、あなたがもうすべきでないこと。)

一部のLinuxカーネルコードにアセンブラスニペットが表示されます。ごく最近、私はそれをスピンロックと他の同期コードで閲覧しました。これらのコードは、アトミックテストセット操作、キャッシュ操作などにアクセスする必要があります。

ほとんどの一般的なプログラミングで、最新のCコンパイラを最適化することは難しいと思います。

@altCognitoに同意するのは、おそらくあなたの時間は、問題についてより深く考え、より良いことをするために費やした方が良いでしょう。何らかの理由で、プログラマーはしばしばマイクロ効率に焦点を合わせ、マクロ効率を無視します。パフォーマンスを向上させるアセンブリ言語は、非常に効率的です。システムをより広く表示するために後退すると、システムのマクロの問題が明らかになる可能性があります。マクロの問題を解決すると、多くの場合、パフォーマンスが向上します。マクロの問題が解決したら、ミクロレベルに崩壊します。

ミクロの問題は、単一のプログラマーの制御の範囲内で、より小さな領域にあると思います。マクロレベルで動作を変更するには、より多くの人々とのコミュニケーションが必要です-一部のプログラマーはこれを避けています。その全体のカウボーイ対チームの事。

15
DanM

"はい"。ただし、アセンブラーでコードを記述する利点はほとんどの場合、努力する価値がないことを理解してください。議会でそれを書くことで得られる利益は、単に問題についてより深く考えることに焦点を合わせ、より良い方法を考えるためにあなたの時間を費やすよりも小さい傾向があります。

Quakeの作成を主に担当したJohn CarmackとMichael Abrash、およびIDゲームエンジンに送られたすべての高性能コードは、この book で詳細に説明します。

また、今日、コンパイラは非常にスマートであり、多くの場合、隠れたアーキテクチャブーストを利用する多くの手法を採用しているというlala Waageに同意します。

10
cgp

最近では、少なくともシーケンシャルコードの場合、まともなコンパイラは、ほとんどの場合、経験豊富なアセンブリ言語プログラマでさえも負けています。しかし、ベクトルコードの場合は別の話です。広く配備されたコンパイラーは、x86 SSEユニットのベクトル並列機能を活用するような素晴らしい仕事をしていません。私はコンパイラー・ライターであり、SSEを悪用することは、コンパイラを信頼する代わりに自分で進める理由のリストのトップです。

9
Norman Ramsey

SSEコードは、少なくともMSVCでは、コンパイラ組み込み関数よりもアセンブリで機能します。 (つまり、データの余分なコピーを作成しません)

8
Macke

欠陥は行ごとに実行される傾向があります(ステートメント、コードポイントなど)。ほとんどの問題では、Assemblyが高レベルの言語よりもはるかに多くの行を使用するのは事実ですが、時折、それが現在の問題に最適な(最も簡潔で、最も少ない行)マッピングになる場合があります。これらのケースのほとんどは、組み込みシステムのドライバーやビットバンギングなど、通常の容疑者に関係しています。

5
Justin Love

一部の命令/フラグ/コントロールは、単にCレベルにはありません。

たとえば、x86でのオーバーフローのチェックは単純なオーバーフローフラグです。このオプションはCでは使用できません。

5
Unknown

仕事中のソースには、3つまたは4つのアセンブラルーチン(約20 MBのソース)があります。それらはすべて SSE(2) であり、(かなり大きい-2400x2048以上を考える)イメージの操作に関連しています。

趣味のために、私はコンパイラに取り組んでおり、そこにはより多くのアセンブラがあります。ランタイムライブラリは非常に頻繁にそれらでいっぱいであり、それらのほとんどは、通常の手続き型を無視するもの(例外のヘルパーなど)に関係しています。

マイクロコントローラー用のアセンブラーがありません。最新のマイクロコントローラーのほとんどは、周辺機器のハードウェアが非常に多いため(割り込み制御カウンター、さらには quadrature encoder sおよびシリアルビルディングブロックさえ)、アセンブラーを使用してループを最適化する必要はほとんどありません。現在のフラッシュ価格では、コードメモリにも同じことが言えます。また、多くの場合、ピン互換デバイスの範囲があるため、CPUの電源またはフラッシュスペースを体系的に使い果たした場合のアップスケーリングは、多くの場合問題ではありません。

実際に100000個のデバイスを出荷し、プログラミングアセンブラを使用すると、フラッシュチップをより小さなカテゴリに収めることで大幅な節約が可能になります。しかし、私はそのカテゴリーに属していません。

多くの人が組み込みはアセンブラーの言い訳だと思っていますが、コントローラーはマシンよりも多くのCPUパワーを持っています nix が開発されました。 (マイクロチップには40および60が付属しています [〜#〜] mips [〜#〜] 以下のマイクロコントローラー [〜#〜] usd [〜#〜] 10)。

しかし、多くの人々はマイクロチップアーキテクチャの変更は容易ではないため、レガシーにこだわっています。また、HLLコードはアーキテクチャに大きく依存しています(ハードウェア周辺機器、レジスタを使用してI/Oなどを制御するため)。そのため、アセンブラでプロジェクトを維持し続けるのに十分な理由がある場合があります(幸運にも、新しいアーキテクチャに最初から問題を設定できました)。しかし、多くの場合、本当にアセンブラーが必要だと自負しています。

GOTOを使用できるかどうかを尋ねたときに教授が出した答えは今でも気に入っています(ただし、ASSEMBLERとしても読むことができます):」機能が必要な場合は、使用できます。結果とともにエッセイを送信してください。 "

低レベル機能の指針としてそれを使用しました。 use屈すぎて使用しないでください。ただし、適切に動機付けしてください。正当化として複雑な推論を回避するために、人工的な障壁を1つまたは2つ(エッセイのように)投げつけます。

4

別の理由としては、利用可能なコンパイラーがアーキテクチャーに十分ではなく、プログラムに必要なコードの量がプログラマーに迷うほど長くも複雑でもない場合があります。組み込みシステム用のマイクロコントローラをプログラミングしてみてください。通常はアセンブリがはるかに簡単になります。

3
alkar

他の言及されたものに加えて、すべての高言語には特定の制限があります。そのため、コードを完全に制御するために、ASMでプログラミングすることを選択する人がいます。

他の人は、20-60KBの範囲の非常に小さな実行可能ファイルを楽しんでいます、例えば、チェック HiEditor 、これはHiEditコントロールの作成者によって実装され、Windows用の優れた強力な編集コントロールです50kb)。私のコレクションには、Excelのスシートからhtmlレンダリングまで、20を超えるゴールドコントロールがあります。

3
majkinetor

多くのゲーム開発者は、このわずかな情報に驚かされると思います。

私が知っているほとんどのゲームは、可能な限り小さなアセンブリとして使用しています。場合によっては、まったく何もせず、最悪の場合は1つまたは2つのループまたは関数です。

この引用は一般化されすぎており、10年前ほど真実ではありません。

しかし、ちょっとした事実は、アセンブリを支持する真のハッカーの十字軍を妨げるべきではありません。 ;)

3
jalf

128バイトのRAMと4Kのプログラムメモリでローエンドの8ビットマイクロコントローラをプログラミングしている場合、アセンブリを使用することについて多くの選択肢がありません。アセンブリ言語は、命令をカウントし、コードで使用されるクロックサイクルを測定できるため便利です。

3
IanW

前回アセンブラーで書いたのは、libcフリーの位置に依存しないコードを生成するようコンパイラーを説得できなかったときです。

次回もおそらく同じ理由でしょう。

もちろん、他の reasons を使用していました。

2
Joshua

非常に小さなCPUでの非常に小さなプロジェクトは別として、アセンブリ全体でプロジェクト全体をプログラムすることは考えていません。ただし、いくつかの内部ループの戦略的なハンドコーディングを使用すると、パフォーマンスのボトルネックを軽減できることがわかります。

場合によっては、実際に必要なのは、一部の言語構造を、オプティマイザーが使用方法を理解することを期待できない命令に置き換えることだけです。典型的な例は、ベクトル演算と積和演算がオプティマイザにとって発見が困難であるが、コーディングが簡単なDSPアプリケーションです。

たとえば、SH4の特定のモデルには、4x4マトリックスと4つのベクトル命令が含まれています。ハードウェアの仮定に合わせて補正行列を4x4に拡大するわずかなコストで、3x3行列の同等のC演算を適切な命令に置き換えることにより、色補正アルゴリズムの巨大パフォーマンスの改善を見ました。これは、12行以下のアセンブリを記述し、関連するデータ型とストレージのマッチング調整を周囲のCコードの少数の場所に運ぶことで達成されました。

2
RBerteig

私が続けている唯一のアセンブラーコーディングは、リソースが乏しい組み込みハードウェア向けです。 leanderが言及しているように、Assemblyは、コードを高速かつ十分に理解する必要がある [〜#〜] isr [〜#〜] sに依然として適しています。

私の2番目の理由は、アセンブリの知識を機能的に保つことです。 CPUが私の入札を行うために取っているステップを調べて理解できるのは、いい感じです。

2
ParoXoN

ゲームはかなりパフォーマンスに飢えていますが、その間、オプティマイザーはかなり優れていますが、「マスタープログラマー」は、アセンブリの適切な部分を手作業でコーディングすることで、さらにパフォーマンスを絞ることができます。

最初にプロファイリングせずにプログラムの最適化を開始しないでください。プロファイリングがボトルネックを特定できた後、より優れたアルゴリズムなどを見つけられなくなった場合は、Assemblyでいくつかのコードを作成してみてください。

2
robert.berger

これまでに見たほぼすべての中規模から大規模のゲームエンジンまたはライブラリには、4x4マトリックス連結などのマトリックス操作に使用できるいくつかの手動最適化アセンブリバージョンがあります。コンパイラーは、大きな行列を操作する場合、いくつかの巧妙な最適化(レジスターの再利用、ループの展開、最大限の効率化、マシン固有の命令の活用など)を避けられないようです。これらのマトリックス操作関数も、ほとんど常にプロファイル上の「ホットスポット」です。

また、FastDelegateのようなものですが、コンパイラーとマシン固有のカスタムディスパッチのために、ハンドコーディングされたアセンブリが多く使用されているのを見ました。

最後に、割り込みサービスルーチンがある場合、asmは世界ですべての違いを生むことができます-割り込みの下で発生させたくない特定の操作があり、割り込みハンドラに「高速で出入りする」ことが必要です。 ..あなたはほとんどexactly asmにある場合、ISRで何が起こるかを知っており、血なまぐさいものを短く保つことをお勧めします(とにかく良い習慣です)。

2
leander

多くの人はアセンブリ言語を中傷するのが大好きです。アセンブリ言語でコーディングすることを一度も学んだことがなく、あいまいにしか遭遇せず、アセンブリ言語を驚かせたり、やや脅迫したりしているからです。真の才能あるプログラマーは、CまたはAssemblyを無料で使用するのは無意味であることを理解します。実際、一方の利点は他方の欠点です。 Cの組織化された構文規則は明快さを向上させますが、それと同時に、アセンブリが構造規則から解放されることによるすべての力を放棄します! Cコード命令は、プログラミングの意図を明確にするために議論される可能性がある非ブロッキングコードを作成するために行われますが、これは電力損失です。 Cでは、コンパイラはif/elseif/else/end内のジャンプを許可しません。または、互いに重複する異なる変数に2つのfor/endループを書くことは許可されていません。自己修正コードを書くことはできません(またはシームレスな簡単な方法で書くことはできません)。これらのアプローチは従来のルールに従うために提起されてきたため、これらのアプローチの力をどのように使用するかさえ考えられません。真実はここにあります:今日、私たちはそれらを使用するアプリケーションよりもはるかに多くのことを行う計算能力を備えたマシンを持っていますが、人間の脳はルールフリーコーディング環境(=アセンブリ)でそれらをコーディングすることができず、非常に制限的なルールを必要としますスペクトルを削減し、コーディングを簡素化します。上記の制限のために非常に非効率になることなく、Cコードで記述できないコードを自分で作成しました。そして、私はまだほとんどの人がアセンブリで書く主な理由だと思う速度について話していない、それはあなたがCで考えることに制限されているなら、あなたは永遠にあなたのコンパイラの奴隷であるということです。 Cプログラマーは「Dames」をプレイするだけで、チェスプレーヤーのマスターは理想的なアセンブリプログラマーだといつも思っていました。

2
Eric W

それは言及されていないようですので、私はそれを追加すると思いました:現代のゲーム開発では、書かれているアセンブリの少なくとも一部はCPU用ではないと思います。 シェーダープログラム の形式のGPU用です。

これは、あらゆる種類の理由で必要になる場合があります。使用される高レベルのシェーディング言語では、正確な操作を必要な命令の正確な数で表現できず、サイズの制約、速度、または任意の組み合わせに合うためです。アセンブリ言語プログラミングの場合と同じように、私は推測します。

2
unwind

私は、1人の開発者にアセンブリの使用について個人的に話しました。彼はポータブルmp3プレーヤーのコントロールを扱うファームウェアに取り組んでいました。 Assemblyで作業を行うには、2つの目的がありました。

  1. 速度:遅延は最小限にする必要があります。
  2. コスト:コードを最小限に抑えることで、コードを実行するために必要なハードウェアの性能がわずかに低下する可能性があります。数百万個のユニットを大量生産する場合、これは加算されます。
2
Paul Williams

Y2K修復のすべての取り組みに参加していた場合、議会を知っていれば、多額のお金を稼ぐことができたでしょう。その中に書かれたレガシーコードがまだたくさんあり、そのコードは時々メンテナンスが必要です。

2
DOK

速度はなくなりましたが、コントロール。速度は制御から得られることもありますが、アセンブリでコードを作成するのは理由のみです。他のすべての理由は、制御に要約されます(つまり、SSEおよびその他の最適化、デバイスドライバー、デバイス依存コードなど)。

1
Kelden Cowan

私はかつてプログラマーがアセンブリコードで書いていたDSPプロジェクトを引き継ぎましたが、Cで書かれたトーン検出ロジックを除き、浮動小数点(固定小数点DSPで!)を使用していました。トーン検出ロジックは、リアルタイムの約1/20で実行されました。

ほぼすべてをゼロから書き直しました。いくつかの小さな割り込みハンドラーと、割り込み処理と低レベル周波数検出に関連する数十行のコードを除き、ほとんどすべてがCにありました。これらは、古いコードの100倍以上の速度で実行されます。

心に留めておくべき重要なことは、多くの場合、特に手書きアセンブラーがすべてをレジスターに収めることができるがコンパイラーはそうではない場合、小さなルーチンのほうが大きなルーチンよりも大幅に高速化できる可能性があることです。かなり管理します。ループが十分に大きく、すべてをレジスタに保持できない場合、改善の機会ははるかに少なくなります。

1
supercat

私はここ数年アセンブリで書いていませんでしたが、私が使っていた2つの理由は次のとおりです。

私は再びアセンブリのコーディングを見続けていますが、それはその挑戦と喜びに過ぎません。そうする理由は他にありません:-)

1
Chris J

[〜#〜] gcc [〜#〜] およびVisual C++ 2008(Visual C++ 9.0としても知られています)を上回ることができれば、人々はそれがどのように可能かについて私にインタビューすることに興味があります。

これが、今のところ私がAssemblyで物事を読み、必要なときに__asm int 3を書くだけの理由です。

この助けを願っています...

1
Mandrake

Dalvik VM JavaアプリケーションのAndroid電話はディスパッチャにアセンブラを使用します。これ 映画 (約31分ですが、映画全体を見る価値があります!)

「まだ、人間がコンパイラよりも優れている場合があります」。

0
Will

私はそうしませんが、少なくとも試してみて、将来のある時点で一生懸命努力することを目指しました(まもなく願わくば)。低レベルのものと、高レベル言語でプログラミングしているときに舞台裏で物事がどのように機能するかをもっと知ることは悪いことではありません。残念ながら、開発者/コンサルタントおよび親としてフルタイムの仕事をするのは困難です。しかし、私は時間通りに行く時に与えるでしょう、それは確かです。

0
Henric