web-dev-qa-db-ja.com

コードを書くとき、コンパイルされたマシンコードについて考える必要がありますか?

たとえば、私は次のコードを持っています:

auto z = [](int x) -> int {
    if (x > 0) {
        switch (x) {
            case 2: return 5;
            case 3: return 6;
            default: return 1;
            }
        }
    return 0;
    };

後でこれを数回呼びます。 asmコードでは、ラムダを使った外部呼び出しが表示されます。それで、おそらく私はメタプログラミングで勝ちますが、asmのデバッグとパフォーマンスで負けますか?パフォーマンスとデバッグの簡素化を確実にするために、現代の言語機能、マクロ、およびその他のメタプログラミングの側面を避けるべきですか?

20
cnd

コードを書くとき、コンパイルされたマシンコードについて考える必要がありますか?

いいえ、初めてコードを作成するときではなく、実際の測定可能なパフォーマンスの問題に悩まされることはありません。ほとんどのタスクでは、これが標準的なケースです。最適化について時期尚早に考えることは「時期尚早の最適化」と呼ばれ、D。クヌースがそれを "すべての悪の根源" と呼んだ理由はいくつかあります。

はい、実際に証明可能なパフォーマンスのボトルネックを測定し、その特定のラムダ構造を根本原因として特定した場合。この場合、Joel Spolskyの "leaky abstractionsの法則" を覚えて、asmレベルで何が起こるかを考えるのは良い考えです。ただし、ラムダ構成要素を「それほど現代的でない」言語構成要素で置き換えると、パフォーマンスの向上がどれほど小さいかに驚かれる場合があります(少なくとも、まともなC++コンパイラを使用している場合)。

59
Doc Brown

Lambdaとfunctor-classの間の選択はトレードオフです。

ラムダからの利益は、ボイラープレートの量を最小化し、概念的に関連するコードをインラインで(それを(すぐにまたは後で)使用する予定の関数内に)書けるようにすることにより、ほとんどが構文的です。

パフォーマンスの面では、これは functor class よりも悪くありません。これは、単一の「メソッド」を含むC++構造体またはクラスです。実際、コンパイラはラムダを、コンパイラが生成したファンクタクラスと同じように舞台裏で扱います。

// define the functor method somewhere
struct some_computer_generated_gibberish_0123456789
{
    int operator() (int x) const
    {
        if (x == 2) return 5;
        if (x == 3) return 6;
        return 0;
    }
};

// make a call
some_computer_generated_gibberish_0123456789 an_instance_of_0123456789;
int outputValue = an_instance_of_0123456789(inputValue);

コードの例では、パフォーマンス面では関数呼び出しと同じです。これは、そのファンクタークラスには状態がなく(空のキャプチャ句があるため)、割り当て、コンストラクター、破棄が必要ないためです。

int some_computer_generated_gibberish_0123456789_method_more_gibberish(int x)
{
    if (...) return ...;
    return ...;
}

逆アセンブラを使用して重要なC++コードをデバッグすることは、常に困難な作業でした。これは、ラムダの使用の有無にかかわらず当てはまります。これは、C++コンパイラによる高度なコード最適化が原因で発生し、その結果、並べ替え、インターリーブ、デッドコードの除去が行われました。

名前マングリングの側面はやや不快で、デバッガーによるラムダのサポートは まだ初期段階 です。デバッガのサポートが時間とともに改善することを期待することができます。

現在、ラムダコードをデバッグする最良の方法は、ソースコードレベルでのブレークポイントの設定をサポートするデバッガを使用することです。つまり、ソースファイル名と行番号を指定します。

8
rwong

@DocBrownの回答に加えて、最近のCPUは安価ですが、労働力が高価であることを覚えておいてください。

プログラムの全体的なコストにおいて、ハードウェアは通常、メンテナンスのコストと比較して取るに足らないものです。これは、典型的なプロジェクトの中で最も高価な部分です(開発よりもはるかに高価です)。

したがって、パフォーマンスが重要な場合を除いて、コードはmaintenanceを何よりも最適化する必要があります(メンテナンスを考慮する必要がある場合でも)。

3
Paddy Landau