gcc
現在、 (テスト済みバージョン:4.8.4)で奇妙な効果が発生しています。
かなり高速に実行されるパフォーマンス指向のコードがあります。その速度は、多くの小さな関数をインライン化することに大きく依存します。
複数の.c
ファイルにまたがるインライン化は難しいため (-flto
まだ広く利用できるようにはなっていません)、多くの小さな関数 (通常はそれぞれ 1 行から 5 行のコード) を共通の C ファイルに保存し、そこにコーデックを開発しています。関連するデコーダー。私の標準では「比較的」大きいですが (約 2000 行ですが、多くはコメントと空白行だけです)、小さな部分に分割すると新しい問題が発生するため、可能であればそれを避けたいと思います。
Encoder と Decoder は逆の操作であるため、関連しています。しかし、プログラミングの観点から見ると、これらは完全に分離されており、いくつかの typedef と非常に低レベルの関数 (整列されていないメモリ位置からの読み取りなど) を除いて、共通点はありません。
奇妙な効果はこれです:
fnew
最近、エンコーダ側に新しい機能を追加しました。新しい「入り口」です。ファイル内のどこからも使用されず、呼び出されません.c
。
それが存在するという単純な事実は、デコーダー機能のパフォーマンスをfdec
大幅に低下させ、20% 以上低下させます。これは、無視するには多すぎます。
ここで、エンコード操作とデコード操作は完全に分離されており、ほとんど何も共有されておらず、いくつかのマイナーな操作typedef
(u32
などu16
) と関連する操作 (読み取り/書き込み) を除いて覚えておいてください。
新しいエンコーディング関数fnew
を として定義するstatic
と、デコーダのパフォーマンスがfdec
向上し、通常の状態に戻ります。fnew
から呼び出されないので.c
、存在しないのと同じだと思います (デッド コードの削除)。
static fnew
がエンコーダ側から呼び出されるようになった場合、 のパフォーマンスはfdec
引き続き強力です。
しかし、fnew
変更されるとすぐに、fdec
パフォーマンスが大幅に低下します。
変更がしきい値を超えたと仮定して、次のパラメーターfnew
を増やしました: (デフォルトでは、その値は 40 であると想定されています) 。gcc
--param max-inline-insns-auto=60
fdec
fnew
そして、このゲームは、小さな変更やその他の類似のもののたびに永遠に続くと思います。さらに微調整が必要です.
これは単純に奇妙です。fnew
function の小さな変更が、まったく関係のない function に影響を与えるという論理的な理由はありませんfdec
。これは、関係だけが同じファイルにあるはずです。
これまでのところ、私が考案できる唯一の暫定的な説明は、単に存在するだけで、に影響を与えるfnew
何らかの種類の を越えるのに十分であるということです。1. 存在しない、2.しかしどこからも呼び出されない、3 . インライン化できるほど小さい。しかし、それは問題を隠しているだけです。新しい機能を追加できないということですか?global file threshold
fdec
fnew
static
static
本当に、ネットのどこにも満足のいく説明が見つかりませんでした。
誰かがすでに同等の副作用を経験しており、その解決策を見つけているかどうか知りたいと思っていました.
[編集]
もっとクレイジーなテストに行きましょう。今、私はただ遊ぶためだけに、まったく役に立たない別の関数を追加しています。内容は厳密には のコピペですfnew
が、明らかに関数名が違うので としましょうwtf
。
がwtf
存在する場合、fnew
が静的であるかどうかも、 の値が何であるかも問題ではありませんmax-inline-insns-auto
。 のパフォーマンスはfdec
正常に戻ります。どこからもwtf
使用も呼び出しもされていませんが... :'(
【編集2】inline
指示
がありません。すべての機能は通常またはstatic
. インライン化の決定は、これまでのところ問題なく機能しているコンパイラの領域内でのみ行われます。
[編集 3]
Peter Cordes が示唆したように、この問題はインラインではなく、命令の配置に関係しています。新しい Intel CPU (Sandy Bridge 以降) では、ホット ループは 32 バイト境界に揃えることでメリットがあります。問題は、デフォルトでは、gcc
それらを 16 バイト境界に揃えることです。これにより、前のコードの長さに応じて、50% の確率で適切な位置合わせが行われます。したがって、「ランダムに見える」問題を理解するのは困難です。
すべてのループがセンシティブなわけではありません。これはクリティカル ループでのみ重要であり、アライメントが理想的ではない場合に、ループの長さが 32 バイトの命令セグメントをさらに 1 つ超える場合にのみ重要です。