平均して、アセンブリは現代のゲームコードでどれくらいの頻度で使用されますか?
特に、x86、PPC、ARMなどの優れたC ++コンパイラを既に搭載しているプラットフォームでは、組み込みシステムのゲームはアセンブリを広範囲に使用すると想定しているためです。
平均して、アセンブリは現代のゲームコードでどれくらいの頻度で使用されますか?
特に、x86、PPC、ARMなどの優れたC ++コンパイラを既に搭載しているプラットフォームでは、組み込みシステムのゲームはアセンブリを広範囲に使用すると想定しているためです。
回答:
答えは、「ゲーム」の意味と「使用」に少し依存します。「使用済み」は「特定のゲームプロジェクトの過程で作成された」ことを意味すると想定します。
私の経験と話をした人からの逸話的データで:
アセンブリ言語の知識は、ゲーム業界での仕事には期待されていませんが、作成するゲームの種類によっては有利になる場合があります。
以前は、コンパイラがCコードの最適化において、手書きのアセンブリを使用する人間よりも優れた仕事をしているという議論がありました。通常、それは真実です、時にはそれは偽です。しかし最近では、CPUの複雑化と「スケールアウト」(つまり、プロセッサの分離)の必要性の組み合わせにより、最適化の努力は通常他の場所で費やされています。
近年、ゲームコードでアセンブリを見たのは__asm int 3
、ブレークポイントを強制するステートメントだけでした。アセンブリの個人的な用途は、異常なクラッシュバグを診断するための関数の逆アセンブリを調べることだけでした。
現代のコンソールゲームの高性能コードの大部分は、アセンブリとC ++の間の一種の中間地点であるコンパイラ組み込み関数を使用して記述されています。これらのコンストラクトはC ++関数のように見え、解析されますが、実際には単一のマシン命令に変換されます。したがって、たとえば、「ベクトルVの各値を> = aおよび<= bにクランプする」関数は次のようになります。
// for each v.x, ensure v.x >= a.x && v.x <= b.x
inline __m128 ClampSIMD( const __m128 &v, const __m128 & a, const __m128 & b )
{
return _mm_max_ps( a, _mm_min_ps( v, b ) );
}
このような関数では、特定のマシン命令に関してまだ考えていますが、レジスターの色付けやスケジューリング、ロードオペレーションやその他の退屈な詳細を心配する必要がないように、Cで記述するのが便利です。
特に現代のコンパイラーはコードをベクトル化するのがひどいので、賢い人間がどれだけうまくやれるかと比較して、CPUがサポートする命令を認識する必要があります。また、コードの配置方法の微妙な詳細がパフォーマンスに大きな影響を与える場合がありますが、これはマシンが何をしているのかを理解しないと明らかではありません。
アセンブリでコーディングすることはできませんが、アセンブリで多くのデバッグを行います。コンパイラーの最適化は、デバッガーが追いつかない方法で積極的にコードを再編成するため、多くの場合、「リリースモード」ビルドをデバッグするときに行う最良の方法は、逆アセンブラを開いてコードをトレースすることです。クラッシュの「フォレンジックデバッグ」に関するこのGDCトークは、そのレベルでのデバッグの多くの理由と方法を示しています。
ハンドアセンブリを必要としていた問題の数は少なくなっています。読みやすさとデバッグ機能が失われると、スピードが向上する可能性があります。また、ほとんどの場合、速度の問題はアセンブリでは改善できないものではないため、コードのセクションの最後の最適化手順の1つとしてのみ実行する必要があります。最近では、CPUの速度は大幅に向上していますが、メモリの速度は向上していません。多くの場合、データがCPUをどのように流れるかを制御することが重要です。
最新のコンパイラーでは、ユーザーが触れたレジスターを処理する必要があるため、アセンブリコードを中心に最適化することも難しく、通常、手作りのコードで命令を並べ替えることはできません。アセンブリの必要性を減らすために、低レベルの概念にアクセスするのに役立つ組み込み関数もありますが、コンパイラーにとって使いやすく、反対にではなくユーザーと連携できるようになっています。
そうは言っても、PS3のSPUは、たとえばここで説明するように手動の命令パイプラインを使用して、プロセッサを最大限に活用するためにアセンブリを使用しなければならない領域の1つです。