web-dev-qa-db-ja.com

インラインアセンブリ言語はネイティブC ++コードよりも遅いですか?

インラインアセンブリ言語とC++コードのパフォーマンスを比較しようとしたため、サイズ2000の2つの配列を100000回追加する関数を作成しました。コードは次のとおりです。

#define TIMES 100000
void calcuC(int *x,int *y,int length)
{
    for(int i = 0; i < TIMES; i++)
    {
        for(int j = 0; j < length; j++)
            x[j] += y[j];
    }
}


void calcuAsm(int *x,int *y,int lengthOfArray)
{
    __asm
    {
        mov edi,TIMES
        start:
        mov esi,0
        mov ecx,lengthOfArray
        label:
        mov edx,x
        Push edx
        mov eax,DWORD PTR [edx + esi*4]
        mov edx,y
        mov ebx,DWORD PTR [edx + esi*4]
        add eax,ebx
        pop edx
        mov [edx + esi*4],eax
        inc esi
        loop label
        dec edi
        cmp edi,0
        jnz start
    };
}

main()は次のとおりです。

int main() {
    bool errorOccured = false;
    setbuf(stdout,NULL);
    int *xC,*xAsm,*yC,*yAsm;
    xC = new int[2000];
    xAsm = new int[2000];
    yC = new int[2000];
    yAsm = new int[2000];
    for(int i = 0; i < 2000; i++)
    {
        xC[i] = 0;
        xAsm[i] = 0;
        yC[i] = i;
        yAsm[i] = i;
    }
    time_t start = clock();
    calcuC(xC,yC,2000);

    //    calcuAsm(xAsm,yAsm,2000);
    //    for(int i = 0; i < 2000; i++)
    //    {
    //        if(xC[i] != xAsm[i])
    //        {
    //            cout<<"xC["<<i<<"]="<<xC[i]<<" "<<"xAsm["<<i<<"]="<<xAsm[i]<<endl;
    //            errorOccured = true;
    //            break;
    //        }
    //    }
    //    if(errorOccured)
    //        cout<<"Error occurs!"<<endl;
    //    else
    //        cout<<"Works fine!"<<endl;

    time_t end = clock();

    //    cout<<"time = "<<(float)(end - start) / CLOCKS_PER_SEC<<"\n";

    cout<<"time = "<<end - start<<endl;
    return 0;
}

次に、プログラムを5回実行して、プロセッサのサイクルを取得します。これは時間と見なすことができます。上記の関数のいずれかを呼び出すたびにのみ。

そして、ここに結果が来ます。

アセンブリバージョンの機能:

Debug   Release
---------------
732        668
733        680
659        672
667        675
684        694
Average:   677

C++バージョンの機能:

Debug     Release
-----------------
1068      168
 999      166
1072      231
1002      166
1114      183
Average:  182

リリースモードのC++コードは、アセンブリコードのほぼ3.7倍高速です。どうして?

私が書いたアセンブリコードは、GCCによって生成されたものほど効果的ではないと思います。私のような一般的なプログラマーは、コンパイラーによって生成される相手よりも速くコードを書くことは難しいのですが、それは、自分の手で書かれたアセンブリー言語のパフォーマンスを信頼し、C++に集中し、アセンブリー言語を忘れてはならないということですか?

172
user957121

はい、ほとんどの時間。

まず第一に、低レベル言語(この場合はアセンブリ)は常に高レベル言語(この場合はC++とC)よりも高速なコードを生成するという誤った仮定から始めます。それは真実ではない。 CコードはJavaコードよりも常に高速ですか?いいえ、別の変数があるので:プログラマー。コードの記述方法とアーキテクチャの詳細に関する知識は、パフォーマンスに大きく影響します(この例で見たように)。

alwaysは、手作りのアセンブリコードがコンパイルされたコードよりも優れている例を生成できますが、通常は、架空の例またはtrue500.000行以上のC++コードのプログラム)。コンパイラーは95%のより良いアセンブリコードを生成すると思います時々、まれにしかありません少数のアセンブリコードを書く必要があるかもしれません、短い、 非常に使用される 、- パフォーマンスクリティカル ルーチン、またはお気に入りの高レベル言語が公開しない機能にアクセスする必要がある場合。この複雑さを少し味わってみませんか?読む この素晴らしい答え SO.

なんでこれ?

まず第一に、コンパイラは想像すらできない最適化を行うことができるため( this short list を参照)、彼らはsecondsでそれらを行います(- 日数が必要な場合があります )。

アセンブリでコーディングするときは、明確に定義された呼び出しインターフェイスを使用して明確に定義された関数を作成する必要があります。ただし、 プログラム全体の最適化 および 手順間の最適化 を考慮することができます- レジスタ割り当て定数伝播共通部分式の除去命令スケジューリング 、およびその他の複雑で明白でない最適化(たとえば、 ポリトープモデル )。 RISC アーキテクチャ担当者は、何年も前にこのことについて心配することを止めました(たとえば、命令のスケジューリングは 手作業で調整する )および最新の CISC CPUには非常に長い パイプライン もあります。

一部の複雑なマイクロコントローラーの場合、systemライブラリーでもアセンブリーではなくCで作成されます。これは、コンパイラーがより良い(そして保守が容易な)最終コードを生成するためです。

コンパイラは時々 MMX/SIMDx命令を自動的に使用する を使用することができ、使用しない場合は単に比較することはできません(他の回答は既にアセンブリコードを十分にレビューしました)。ループの場合、これは ループ最適化の短いリスト コンパイラのチェック対象一般的にです(スケジュールが決定したら、自分でそれを行うことができると思いますか) C#プログラムの場合?)Assemblyで何かを書く場合、少なくともいくつかの 単純な最適化 を考慮する必要があると思います。配列の教科書の例は、 サイクルを展開 (そのサイズはコンパイル時にわかっています)です。それを行い、テストを再度実行します。

最近では、別の理由でアセンブリ言語を使用する必要があることもめったにありません: 多数の異なるCP 。それらすべてをサポートしますか?それぞれには、特定の マイクロアーキテクチャ といくつかの 特定の命令セット があります。それらは異なる数の機能ユニットを持ち、それらをすべてビジーに保つためにアセンブリ命令を配置する必要があります。 Cで記述する場合、 PGO を使用できますが、アセンブリでは、その特定のアーキテクチャに関する十分な知識が必要になります(および別のアーキテクチャのすべてを再考してやり直し)。小規模なタスクの場合、コンパイラは通常によりよく機能し、複雑なタスクの通常は作業に返済されません(および コンパイラmayの方が良い とにかく)。

座ってコードを見ると、おそらくアセンブリに変換するよりもアルゴリズムを再設計する方が得られることがわかります(これを読んでください SOのすばらしい投稿 )アセンブリ言語に頼る前に効果的に適用できる高レベルの最適化(およびコンパイラへのヒント)です。多くの場合、組み込み関数を使用するとパフォーマンスが向上しますが、コンパイラーはほとんどの最適化を実行できることに言及する価値があります。

これは、5〜10倍のアセンブリコードを生成できる場合でも、顧客にpayの1週間your timeまたは- 50ドル高速なCPUを購入。極端な最適化は、ほとんどの場合(特にLOBアプリケーションで)必要とされることはほとんどありません。

241
Adriano Repetti

アセンブリコードは次善であり、改善される可能性があります。

  • 内部ループでレジスタ( EDX )をプッシュおよびポップしています。これはループの外に移動する必要があります。
  • ループの各反復で配列ポインターを再ロードします。これはループの外に移動するはずです。
  • loop命令を使用します。これは、 ほとんどの最新のCPUでは完全に遅いことが知られています (おそらく、古代のアセンブリ本を使用した結果*)
  • 手動のループ展開の利点はありません。
  • 利用可能な SIMD 命令を使用しません。

したがって、アセンブラに関するスキルセットを大幅に改善しない限り、パフォーマンスのためにアセンブラコードを記述することは意味がありません。

*もちろん、あなたが本当に古代アセンブリの本からloopの指示を本当に受けたかどうかはわかりません。しかし、実世界のコードではほとんど見られません。すべてのコンパイラーはloopを出力しないほど賢く、IMHOの古くて古い本でしか見られません。

189
Gunther Piez

アセンブリを掘り下げる前であっても、より高いレベルに存在するコード変換があります。

static int const TIMES = 100000;

void calcuC(int *x, int *y, int length) {
  for (int i = 0; i < TIMES; i++) {
    for (int j = 0; j < length; j++) {
      x[j] += y[j];
    }
  }
}

ループ回転 で変換できます:

static int const TIMES = 100000;

void calcuC(int *x, int *y, int length) {
    for (int j = 0; j < length; ++j) {
      for (int i = 0; i < TIMES; ++i) {
        x[j] += y[j];
      }
    }
}

メモリの局所性に関する限り、これははるかに優れています。

これはさらに最適化でき、a += bをX回実行することはa += X * bを実行することと同等であるため、次のようになります。

static int const TIMES = 100000;

void calcuC(int *x, int *y, int length) {
    for (int j = 0; j < length; ++j) {
      x[j] += TIMES * y[j];
    }
}

しかし、私のお気に入りのオプティマイザー(LLVM)はこの変換を実行しないようです。

[編集]restrictおよびxへのy修飾子がある場合、変換が実行されることがわかりました。 。確かに、この制限がなければ、x[j]y[j]は同じ場所にエイリアスする可能性があり、この変換がエラーになります。 [編集の終了]

とにかく、thisは最適化されたCバージョンだと思います。すでにはるかに簡単です。これに基づいて、ここにASMでの私の亀裂があります(私はClangにそれを生成させます、私はそれで役に立たないです):

calcuAsm:                               # @calcuAsm
.Ltmp0:
    .cfi_startproc
# BB#0:
    testl   %edx, %edx
    jle .LBB0_2
    .align  16, 0x90
.LBB0_1:                                # %.lr.ph
                                        # =>This Inner Loop Header: Depth=1
    imull   $100000, (%rsi), %eax   # imm = 0x186A0
    addl    %eax, (%rdi)
    addq    $4, %rsi
    addq    $4, %rdi
    decl    %edx
    jne .LBB0_1
.LBB0_2:                                # %._crit_Edge
    ret
.Ltmp1:
    .size   calcuAsm, .Ltmp1-calcuAsm
.Ltmp2:
    .cfi_endproc

私はこれらのすべての命令がどこから来たのか理解していないのではないかと心配していますが、いつでも楽しんでそれを比較してみてください...しかし、私はまだコードではアセンブリ1ではなく最適化されたCバージョンを使用しますはるかにポータブル。

59
Matthieu M.

短い答え:はい。

長答:はい、あなたが何をしているか本当に知っていて、そうする理由がない限り。

41

Asmコードを修正しました:

  __asm
{   
    mov ebx,TIMES
 start:
    mov ecx,lengthOfArray
    mov esi,x
    shr ecx,1
    mov edi,y
label:
    movq mm0,QWORD PTR[esi]
    paddd mm0,QWORD PTR[edi]
    add edi,8
    movq QWORD PTR[esi],mm0
    add esi,8
    dec ecx 
    jnz label
    dec ebx
    jnz start
};

リリースバージョンの結果:

 Function of Assembly version: 81
 Function of C++ version: 161

リリースモードのアセンブリコードは、C++よりもほぼ2倍高速です。

33
sasha

それは、自分の手で書かれたアセンブリ言語のパフォーマンスを信頼すべきではないということですか?

はい、それはまさにそれが意味するものであり、そしてそれはevery言語に当てはまります。言語Xで効率的なコードを記述する方法がわからない場合は、Xで効率的なコードを記述する能力を信頼しないでください。したがって、効率的なコードが必要な場合は、別の言語を使用する必要があります。

アセンブリはこれに特に敏感です。なぜなら、あなたが見るものはあなたが得るものだからです。 CPUに実行させる特定の命令を記述します。高水準言語には、コードを変換し、多くの非効率性を取り除くことができるコンパイラーがあります。アセンブリを使用すると、あなた自身でしています。

24
jalf

最近アセンブリ言語を使用する唯一の理由は、言語がアクセスできない機能を使用することです。

これは以下に適用されます。

  • MMUなどの特定のハードウェア機能にアクセスする必要があるカーネルプログラミング
  • コンパイラーでサポートされていない非常に特定のベクターまたはマルチメディア命令を使用する高性能プログラミング。

しかし、現在のコンパイラは非常にスマートです。Cにそのような演算子がない場合でも、d = a / b; r = a % b;のような2つの個別のステートメントを、除算と剰余を一度に計算する単一の命令に置き換えることができます。

21
fortran

最新のコンパイラーがコードの最適化で素晴らしい仕事をしているのは事実ですが、それでもアセンブリーを学び続けることをお勧めします。

まず第一に、あなたは明らかにそれによって脅かされていません、それは素晴らしい、素晴らしいプラスです、次に-速度の仮定を検証または破棄するためのプロファイリング、経験者からの入力を求めていますそして、あなたは人類に知られている最大の最適化ツールを持っています:a brain

経験が増えるにつれて、いつ、どこでそれを使用するかを学習します(通常、アルゴリズムレベルで深く最適化した後、コード内で最もタイトで最も内側のループ)。

インスピレーションについては、Michael Abrashの記事を参照することをお勧めします(彼から連絡がない場合、彼は最適化の第一人者であり、彼はQuakeソフトウェアレンダラーの最適化におけるJohn Carmack!)

「最速のコードなどはありません」-Michael Abrash

19
user1222021

Asmコードを変更しました:

 __asm
{ 
    mov ebx,TIMES
 start:
    mov ecx,lengthOfArray
    mov esi,x
    shr ecx,2
    mov edi,y
label:
    mov eax,DWORD PTR [esi]
    add eax,DWORD PTR [edi]
    add edi,4   
    dec ecx 
    mov DWORD PTR [esi],eax
    add esi,4
    test ecx,ecx
    jnz label
    dec ebx
    test ebx,ebx
    jnz start
};

リリースバージョンの結果:

 Function of Assembly version: 41
 Function of C++ version: 161

リリースモードのアセンブリコードは、C++よりもほぼ4倍高速です。 IMHo、アセンブリコードの速度はプログラマに依存

14
sasha

非常に興味深いトピックです!
SashaのコードでSSEによってMMXを変更しました
私の結果は次のとおりです。

Function of C++ version:      315
Function of Assembly(simply): 312
Function of Assembly  (MMX):  136
Function of Assembly  (SSE):  62

SSEを含むアセンブリコードは、C++よりも5倍高速です。

12
salaoshi

ほとんどの高水準言語コンパイラは非常に最適化されており、何をしているのかを知っています。逆アセンブルコードをダンプして、ネイティブアセンブリと比較できます。あなたのコンパイラが使用しているいくつかの素晴らしいトリックを見ると思います。

ちょうどたとえば、それがもう正しいかどうかわからない場合でも:):

やること:

mov eax,0

よりも多くのサイクルがかかります

xor eax,eax

同じことをします。

コンパイラはこれらすべてのトリックを知っており、それらを使用します。

12
Nuno_147

コンパイラはあなたを打ち負かしました。試してみますが、保証はいたしません。 TIMESによる「乗算」は、より関連性の高いパフォーマンステストにするためのものであり、yxは16に揃えられ、lengthはゼロ以外であると想定します。 4の倍数。それはおそらくとにかくすべて本当です。

  mov ecx,length
  lea esi,[y+4*ecx]
  lea edi,[x+4*ecx]
  neg ecx
loop:
  movdqa xmm0,[esi+4*ecx]
  paddd xmm0,[edi+4*ecx]
  movdqa [edi+4*ecx],xmm0
  add ecx,4
  jnz loop

私が言ったように、私は何の保証もしません。しかし、はるかに高速に処理できる場合は驚かれます。ここでのボトルネックは、すべてがL1ヒットであってもメモリスループットです。

10
harold

Assemblyで命令ごとにまったく同じアルゴリズムを盲目的に実装するのは、保証コンパイラーが実行できる速度より遅くなるためです。

コンパイラが行う最小の最適化でさえ、最適化をまったく行わない厳格なコードよりも優れているからです。

もちろん、コンパイラーを打ち負かすことは可能です。特に、それがコードの小さなローカライズされた部分である場合、私はそれを自分でやらなくてはなりませんでした。 4倍高速化されますが、この場合、ハードウェアに関する十分な知識と、一見すると直感に反する多数のトリックに大きく依存する必要があります。

6
vsz

コンパイラとして、多くの実行タスクのループを固定サイズに置き換えます。

int a = 10;
for (int i = 0; i < 3; i += 1) {
    a = a + i;
}

生産します

int a = 10;
a = a + 0;
a = a + 1;
a = a + 2;

そして、最終的に「a = a + 0;」であることがわかります。役に立たないので、この行を削除します。頭の中で何かが最適化オプションをコメントとして付けてくれることを願っています。これらの非常に効果的な最適化はすべて、コンパイルされた言語を高速化します。

5
Miah

それはまさにそれが意味するものです。マイクロ最適化はコンパイラーに任せます。

4
Luchian Grigore

この例は、低レベルコードに関する重要な教訓を示しているので気に入っています。はい、あなたはcan Cコードと同じくらい速いアセンブリを書きます。これはトートロジー的には正しいですが、必ずしもmean何でもありません。明らかにsomebodyは可能です。そうしないと、アセンブラは適切な最適化を知りません。

同様に、言語の抽象化の階層を上るのと同じ原則が適用されます。はい、あなたはcan迅速で汚いPerlスクリプトと同じくらい速いCでパーサーを書きます、そして多くの人がします。ただし、Cを使用したためにコードが高速になるわけではありません。多くの場合、高水準言語は、これまで考えたこともないような最適化を行います。

4
tylerl

多くの場合、一部のタスクを実行する最適な方法は、タスクが実行されるコンテキストによって異なります。ルーチンがアセンブリ言語で書かれている場合、通常、コンテキストに基づいて一連の命令を変更することはできません。簡単な例として、次の簡単な方法を検討してください。

inline void set_port_high(void)
{
  (*((volatile unsigned char*)0x40001204) = 0xFF);
}

上記の32ビットARMコードのコンパイラは、おそらく次のようにレンダリングします。

ldr  r0,=0x40001204
mov  r1,#0
strb r1,[r0]
[a fourth Word somewhere holding the constant 0x40001204]

多分

ldr  r0,=0x40001000  ; Some assemblers like to round pointer loads to multiples of 4096
mov  r1,#0
strb r1,[r0+0x204]
[a fourth Word somewhere holding the constant 0x40001000]

次のいずれかのように、手作業で組み立てられたコードでわずかに最適化できます。

ldr  r0,=0x400011FF
strb r0,[r0+5]
[a third Word somewhere holding the constant 0x400011FF]

または

mvn  r0,#0xC0       ; Load with 0x3FFFFFFF
add  r0,r0,#0x1200  ; Add 0x1200, yielding 0x400011FF
strb r0,[r0+5]

両方の手作業によるアプローチでは、16バイトではなく12バイトのコードスペースが必要です。後者は「ロード」を「追加」に置き換え、ARM7-TDMIで2サイクル高速に実行します。したがって、コードがr0が認識しない/認識しないコンテキストで実行される場合、アセンブリ言語のバージョンはコンパイルされたバージョンよりもいくらか優れています。一方、コンパイラーが何らかのレジスターを知っていると仮定します。 r5]は、目的のアドレス0x40001204の2047バイト以内の値を保持しようとしていました。 0x40001000]、さらに他のレジスタ[e.g. r7]は、下位ビットが0xFFの値を保持しようとしていました。その場合、コンパイラーはCバージョンのコードを最適化して次のように単純化できます。

strb r7,[r5+0x204]

手作業で最適化されたアセンブリコードよりもはるかに短くて高速です。さらに、コンテキストでset_port_highが発生したとします。

int temp = function1();
set_port_high();
function2(temp); // Assume temp is not used after this

組み込みシステム用にコーディングする場合、まったく信じがたいことではありません。 set_port_highがアセンブリコードで記述されている場合、コンパイラは、アセンブリコードを呼び出す前にr0(function1からの戻り値を保持している)を別の場所に移動し、その後その値をr0に戻す必要があります( function2はr0)の最初のパラメーターを予期するため、「最適化された」アセンブリコードには5つの命令が必要です。コンパイラが格納するアドレスまたは値を保持するレジスタを知らなかった場合でも、その4つの命令バージョン(利用可能なレジスタを使用するように適応できます。必ずしもr0およびr1である必要はありません)は、「最適化された」アセンブリ-言語バージョン。コンパイラが前述のようにr5とr7に必要なアドレスとデータを持っている場合、function1はそれらのレジスタを変更しないため、set_port_highを単一のstrb命令に置き換えることができます--- 4つの命令が小さくて高速「手動で最適化された」アセンブリコードより。

プログラマーが正確なプログラムフローを知っている場合は、手作業で最適化されたアセンブリコードがコンパイラよりも優れている場合がありますが、コンテキストがわかる前にコードの一部が記述されている場合、またはソースコードの一部が複数のコンテキストから呼び出される[コードの50の異なる場所でset_port_highが使用されている場合、コンパイラはそれぞれの拡張方法を個別に決定できます]。

一般に、アセンブリ言語は、非常に限られた数のコンテキストから各コードにアクセスできる場合に最大のパフォーマンスの改善をもたらす傾向があり、特定の場所でのパフォーマンスに有害な傾向があることをお勧めします。コードには多くの異なるコンテキストからアプローチできます。興味深いことに(そして便利なことに)、アセンブリがパフォーマンスにとって最も有益なケースは、多くの場合、コードが最も簡単で読みやすいケースです。アセンブリ言語のコードがゴチャゴチャになる場所は、多くの場合、アセンブリでの書き込みがパフォーマンスのメリットを最小限に抑える場所です。

[小さな注意:アセンブリコードを使用して、非常に最適化されたネバネバした混乱を生み出すことができる場所がいくつかあります。たとえば、ARMからWordをフェッチし、値の上位6ビット(多くの値)に基づいて約12のルーチンのいずれかを実行するために必要なRAMに対して行ったコード同じルーチンにマップされます)。私はそのコードを次のようなものに最適化したと思います:

ldrh  r0,[r1],#2! ; Fetch with post-increment
ldrb  r1,[r8,r0 asr #10]
sub   pc,r8,r1,asl #2

レジスタr8は常にメインディスパッチテーブルのアドレスを保持していました(コードがその時間の98%を費やすループ内では、他の目的に使用されることはありませんでした)。 64エントリすべてが、その前の256バイトのアドレスを参照しました。ほとんどの場合、プライマリループには約60サイクルという厳しい実行時間制限があるため、9サイクルのフェッチとディスパッチは、その目標を達成する上で非常に役立ちました。 256個の32ビットアドレスのテーブルを使用すると、1サイクルは高速になりますが、1KBの非常に貴重なRAM [フラッシュにより複数の待機状態が追加されます]。 64個の32ビットアドレスを使用するには、フェッチしたWordの一部のビットをマスクする命令を追加する必要があり、実際に使用したテーブルよりも192バイト多くのバイトを消費していました。 8ビットオフセットのテーブルを使用すると、非常にコンパクトで高速なコードが得られましたが、コンパイラが思い付くことは期待できませんでした。また、コンパイラがテーブルアドレスを保持するためにレジスタを「フルタイム」専用にすることも期待していません。

上記のコードは、自己完結型システムとして実行するように設計されています。定期的にCコードを呼び出すことができますが、通信しているハードウェアが16ミリ秒ごとに約1ミリ秒の間隔で「アイドル」状態にできるのは特定の時間だけです。

3
supercat

正しい方法でより深い知識を持つアセンブリ言語を使用している場合を除き、C++は高速です。

ASMでコーディングするとき、論理的に可能な場合にCPUが命令の多くを並行して実行できるように、命令を手動で再編成します。たとえば、ASMでコーディングする場合、RAMをほとんど使用しません。ASMには20000行以上のコードがあり、プッシュ/ポップを使用したことがありません。

潜在的にオペコードの途中にジャンプして、自己修正コードのペナルティなしでコードと動作を自己修正できます。レジスタへのアクセスには1ティック(場合によっては.25ティック)のCPUが必要です。RAMへのアクセスには数百かかる可能性があります。

前回のASMの冒険では、変数を格納するためにRAMを一度も使用しませんでした(ASMの何千行も)。 ASMは、C++よりも想像以上に高速である可能性があります。ただし、次のような多くの可変要素に依存します。

1. I was writing my apps to run on the bare metal.
2. I was writing my own boot loader that was starting my programs in ASM so there was no OS management in the middle.

私は生産性が重要だと気付いたので、C#とC++を学んでいます!空き時間に純粋なASMのみを使用して、想像できる限り高速なプログラムを実行することができます。しかし、何かを生成するには、高レベルの言語を使用します。

たとえば、最後にコーディングしたプログラムはJSとGLSLを使用していたため、パフォーマンスの問題に気付くことはありませんでした。これは、3D向けにGPUをプログラミングするという概念だけで、コマンドをGPUに送信する言語の速度がほとんど無関係になるためです。

ベアメタル上のアセンブラーの速度だけが反論できません。 C++内部ではさらに遅くなる可能性がありますか? -それは、最初にアセンブラーを使用していないコンパイラーでアセンブリー・コードを書いているためである可能性があります。

私の個人評議会は、私がアセンブリを愛していても、それを避けることができるなら、アセンブリコードを決して書かないことです。

2
user5921954

最近、私がやったすべての速度の最適化は、脳に損傷を与えた遅いコードを妥当なコードに置き換えることでした。しかし、物事は速度が非常に重要であり、私は何かを速くすることに真剣に努力しました。結果は常に反復プロセスであり、各反復はより少ない操作で問題を解決する方法を見つける、問題に対するより多くの洞察を与えました。最終的な速度は常に、問題に対する洞察力に依存していました。いずれかの段階でアセンブリコード、または最適化されたCコードを使用した場合、より良いソリューションを見つけるプロセスが苦しみ、最終結果が遅くなります。

2
gnasher729

ここでのすべての答えは、1つの側面を除外しているように見えます。特定の目的を達成するためのコードを書かないこともありますが、それはfunです。投資するのに時間をかけるのは経済的ではないかもしれませんが、おそらく、手動でロールされたasmの代替手段で最速のコンパイラ最適化コードスニペットを破るほど大きな満足感はありません。

0
madoki