5

生成されたオブジェクト ファイルのパフォーマンスやサイズを決定できる C 言語でプログラマーができることを探しています。

たとえば、
1. 単純な get/set 関数をインラインとして宣言すると、パフォーマンスが向上する場合があります (フットプリントが大きくなります)
2. ループ変数自体の値を使用しないループの場合、カウントアップではなくゼロまでカウントダウンします。特定の値など

コンパイラーは、(上記の 2 つのポイントのような) 「単純な」トリックがまったく必要ないレベルまで進歩したようです。コンパイル中の適切なオプションはとにかく仕事をします。また、コンパイラが再帰を処理する方法に関する投稿もここで見ました。これは非常に興味深いものでした。では、C レベルで何をする必要があるのでしょうか。:)

私の特定の環境は次のとおりです。ARMアーキテクチャ(v4)用に再ターゲットされたGCC 4.3.3。しかし、他のコンパイラ/プロセッサに関する回答も歓迎され、むしゃむしゃ食べられます。

PS: 私のこのアプローチは、通常の「最初にコードを作成し、次にベンチマークし、最後に最適化する」というアプローチに反します。

編集:たまたま、質問を投稿した後に同様の投稿を見つけました

4

6 に答える 6

6

コンパイラがおそらく最適化しないと私が考えることができることの1つは、「キャッシュフレンドリー」です。たとえば、行優先の順序で2次元配列を反復処理している場合、内部ループが列インデックス全体で実行されるようにしてください。キャッシュのスラッシングを避けるため。内部ループが間違ったインデックスで実行されると、パフォーマンスが大幅に低下する可能性があります。

これはすべてのプログラミング言語に当てはまりますが、C でプログラミングしている場合、おそらくパフォーマンスが重要になるため、特に重要です。

于 2009-07-15T09:21:06.677 に答える
5

アルゴリズムの時間と空間の複雑さを「常に」知っています。コンパイラは、あなたができるようにその仕事をすることはできません. :)

于 2009-07-15T09:21:17.597 に答える
3

最近のコンパイラは、コードのベクトル化がまだあまり得意ではないため、ほとんどのアルゴリズムの SIMD 実装を自分で行う必要があります。

正確な問題に適したデータ構造を選択すると、パフォーマンスが劇的に向上する可能性があります (その特定のケースでは、Kd ツリーから BVH に移動するとそれが可能になるケースを見てきました)。

コンパイラはキャッシュに収まるように一部の構造体/変数をパディングする場合がありますが、データの局所性などの他のキャッシュの最適化は依然としてユーザー次第です。

私の経験では、コンパイラはコードを自動的にマルチスレッド化するわけではなく、openmp を使用してもあまり役に立ちません。(パフォーマンスを劇的に向上させるには、とにかくopenmpを理解する必要があります)。したがって、現在、あなたは自分でマルチスレッドを行っています。

于 2009-07-15T09:30:40.807 に答える
2

キャッシュの使いやすさについて Martin が上で述べたことに追加するには、次のようにします。

  • 一般的に一緒にアクセスされるフィールドが同じキャッシュ ラインにあるように構造を並べ替えると (たとえば、2 つではなく 1 つのキャッシュ ラインだけをロードすることによって)、データ キャッシュ内の有用なデータの密度が本質的に増加します。これを行うのに役立つ Linux ツールがあります: dwarves 1http://www.linuxinsight.com/files/ols2007/melo-reprint.pdf

  • コードの密度を高めるために同様の戦略を使用できます。gcc では、可能性が高い/可能性が低いタグを使用して、ホット ブランチとコールド ブランチをマークできます。これにより、gcc がコールド ブランチを個別に保持できるようになり、icache 密度の増加に役立ちます。

そして今、完全に異なる何かのために:

  • CPU 間でアクセス (読み取りおよび書き込み) される可能性があるフィールドの場合、反対の戦略が理にかなっています。問題は、コヒーレンスのために、1 つの CPU だけが同じアドレス (実際には同じキャッシュライン) に書き込むことができることです。これにより、キャッシュライン ピンポンと呼ばれる状態が発生する可能性があります。これはかなり悪いことであり、そのキャッシュラインに他の無関係なデータが含まれている場合はさらに悪化する可能性があります。ここで、この競合するデータをキャッシュ ラインの長さにパディングすることは理にかなっています。

注: これらは明らかにマイクロ最適化であり、コードから最後のパフォーマンスを引き出そうとする後の段階でのみ実行されます。

于 2009-07-15T11:45:41.750 に答える
1

可能な場合は事前計算... (申し訳ありませんが、常に可能であるとは限りません... 私はチェスエンジンで大規模な事前計算を行いました.) これらの結果をメモリに保存し、キャッシュを念頭に置いてください.. メモリ内の事前計算データのサイズが大きいほど、メモリ内の事前計算データのサイズは小さくなります.キャッシュヒットの可能性。最近のハードウェアのほとんどはマルチコアであるため、それをターゲットにするようにアプリケーションを設計できます。

いくつかの大きな配列を使用している場合は、それらが使用される場所でそれらを互いに近くにグループ化して、キャッシュ ヒットを増やしてください。

于 2009-07-15T09:28:37.037 に答える
0

多くの人はこれに気づいていません: 意図的にインラインを意味するインライン ラベル (コンパイラによって異なります) を定義します。多くのコンパイラは、元の意味とはまったく異なるコンテキストにキーワードを配置します。コンパイラが些細なことを行からポップし始める前に、インラインサイズの制限を増やす方法もあります。人間が指示したインライン化は、はるかに高速なコードを生成できます (コンパイラーはしばしば保守的であるか、プログラムの十分な説明をしていません)。はい、これはコードサイズと速度に絶対に当てはまります。

于 2009-11-17T14:03:48.507 に答える