15

ASSERT(...)C++ アプリケーションで使用するカスタムマクロがあります。

#include <stdlib.h>
#include <iostream>

/// ASSERT(expr) checks if expr is true.  If not, error details are logged
/// and the process is exited with a non-zero code.
#ifdef INCLUDE_ASSERTIONS
#define ASSERT(expr)                                                      \
    if (!(expr)) {                                                        \
        char buf[4096];                                                   \
        snprintf (buf, 4096, "Assertion failed in \"%s\", line %d\n%s\n", \
                 __FILE__, __LINE__, #expr);                              \
        std::cerr << buf;                                                 \
        ::abort();                                                        \
    }                                                                     \
    else // This 'else' exists to catch the user's following semicolon
#else
#define ASSERT(expr)
#endif

最近、Linux カーネル モジュールのコードを読んでいて、likely(...)unlikely(...)マクロの存在に出会いました。これらは、特定の分岐の可能性が高く、パイプラインがそのパスを最適化する必要があるというヒントを CPU に提供します。

アサーションは、定義により、true (つまりlikely) と評価されることが期待されます。

ASSERTマクロで同様のヒントを提供できますか? ここでの根底にあるメカニズムは何ですか?

明らかに、パフォーマンスの違いを測定しますが、理論的には違いがあるはずですか?

私は自分のコードを Linux でしか実行していませんが、クロスプラットフォームでこれを行う方法があるかどうか知りたいです。gcc も使用していますが、clang もサポートしたいと考えています。

4

3 に答える 3

15

パフォーマンスが大幅に向上する可能性は低いですが、これらの Linux カーネル マクロは次のように定義されています。

#define likely(x)      __builtin_expect(!!(x), 1)
#define unlikely(x)    __builtin_expect(!!(x), 0)

したがって、次のように条件を変更できます (exprそれが true であると!(expr)予想されるため、false であると予想されると仮定します)。

if (__builtin_expect(!(expr), 0)) {

または、カーネルと同じマクロを定義して、読みやすくするためにそれらを使用することもできます。

これは gcc に組み込まれているため、もちろん移植性はありません。

これは、clang もビルトインをサポートしていることを示唆しています。それ以外の場合は、上記のマクロを使用して#define likely(x) (x)、組み込みをサポートしていないコンパイラのように条件付きで定義できます。

あなたの場合、予測はうまくいくでしょう(それか中止するかのどちらかです)ので、悲観するリスクはないはずですが、ビルトインをより広く使用することを検討している場合は、gcc からのアドバイスがありますドキュメンテーション:

一般に、これには実際のプロファイル フィードバック (-fprofile-arcs) を使用することをお勧めします。これは、プログラマーが自分のプログラムが実際にどのように動作するかを予測するのが苦手なことで知られているためです。

于 2014-05-28T11:46:11.530 に答える
11

多くのCPUの場合、likelyおよびunlikely(またはそれ以外のことについては)CPUに分岐ヒントを提供しません(プロファイルガイド付き最適化と同様に、異なる最適化に使用する可能性のあるコンパイラーのみ)。それを行う方法はありません。

たとえば、分岐ヒントは P4 以降 x86 用に定義されています。それ以前は効果がありませんでしたが、さらに悪いことに、P4 以外には効果がありません。したがって、それらは役に立たず (ただし、スペースと帯域幅を無駄にします)、GCC がそれらを発行しないことがわかっている限りです。

ARM には (まだ?) 分岐ヒントもありません。likelyPPC、IA64、および SPARC にはヒント付きの分岐があります。GCC がandを使用するかどうかはわかりませんunlikelyが、少なくとも可能です。

于 2014-05-28T12:15:25.017 に答える