この質問では、Cでは簡単に達成できないソート関数の最適化について説明します: qsortとstd :: sortのパフォーマンス?
C ++と比較した場合、Cで達成することが不可能または少なくとも困難なコンパイラ最適化の例は他にもありますか?
この質問では、Cでは簡単に達成できないソート関数の最適化について説明します: qsortとstd :: sortのパフォーマンス?
C ++と比較した場合、Cで達成することが不可能または少なくとも困難なコンパイラ最適化の例は他にもありますか?
@seheがコメントで述べたように。それは何よりも抽象化についてです。言い換えれば、言語がコーダーが意図をよりよく表現することを可能にする場合、それはより最適な方法でその意図を実装するコードを発することができます。
簡単な例はstd::fill
です。確かに基本的なタイプの場合は、を使用できますmemset
が、32ビットの配列であるとしましょうunsigned long
。配列サイズが32ビットの倍数であることをstd::fill
認識しています。また、コンパイラによっては、配列が32ビット境界に適切に配置されていると想定できる場合もあります。
これらすべてを組み合わせると、コンパイラーは、値を一度に32ビットに設定するコードを発行でき、実行時のチェックが有効であることを確認できなくなります。運が良ければ、コンパイラはこれを認識し、特に効率的なアーキテクチャ固有のバージョンのコードに置き換えます。
memset
(実際には、gccおよびおそらく他の主流のコンパイラーは、実際には、を含む、すでに同等と見なされる可能性のあるほぼすべてのものに対してこれを実行しますstd::fill
)。
多くの場合memset
、最適なコードパスを選択するために、これらのタイプのものを実行時にチェックする方法で実装されます。この違いはおそらく無視できる程度ですが、配列を特定の値で「埋める」意図をより適切に表現したため、コンパイラーはわずかに適切な選択を行うことができます。
他のより複雑な言語機能は、意図の表現を使用してより大きな利益を得るのに適していますが、これは最も単純な例です。
明確にするために、私のポイントは、それstd::fill
がより「優れている」ということではありませんmemset
。代わりに、これは、c ++がコンパイラへの意図のより良い表現を可能にし、コンパイル時に多くの情報を取得できるようにして、いくつかの最適化を実装しやすくする方法の例です。 。
ここでの最適化としてあなたが考えるものに少し依存します。純粋に「std::sort vs. qsort」と考えている場合は、他にも同様の最適化が何千もあります。C ++テンプレートを使用すると、本質的にCで唯一の合理的な代替手段が関数へのポインターを使用することであり、呼び出されるコードをインライン化する既知のコンパイラーがほとんどない状況でのインライン化をサポートできます。視点に応じて、これは単一の最適化、またはそれらの(オープンエンドの)ファミリー全体のいずれかです。
もう1つの可能性は、テンプレートメタプログラミングを使用して、通常は実行時にCで計算する必要があるコンパイル時定数に変換することです。理論的には、通常、マジックナンバーを埋め込むことでこれを行うことができます。これはaからCを介して可能です#define
が、コンテキスト、柔軟性、またはその両方を失う可能性があります(たとえば、C ++では、コンパイル時に定数を定義し、その入力から任意の計算を実行し、残りの部分で使用されるコンパイル時定数を生成できます。で実行できる計算がはるかに限られていることを考えると、それは#define
ほとんど頻繁には不可能です。
さらに別の可能性は、関数のオーバーロードとテンプレートの特殊化です。これらは別々ですが、同じ基本的な結果が得られます。特定のタイプに特化したコードを使用します。Cでは、処理する関数の数を中途半端に保つために、(たとえば)すべての整数をに変換long
して計算を行うコードを作成することがよくあります。テンプレート、テンプレートの特殊化、およびオーバーロードにより、小さいタイプをネイティブサイズに保つコードを比較的簡単に使用できるため、速度が大幅に向上します(特に、数学のベクトル化が可能な場合)。
最後の明らかな可能性は、かなりの数の事前に構築されたデータ構造とアルゴリズムを提供し、そのようなものをパッケージ化して比較的簡単で効率的に再利用できるようにすることから生じます。より効率的なデータ構造やアルゴリズムを見つける(または適応させる)時間の価値がなかったという理由だけで、比較的非効率的なデータ構造やアルゴリズムを使用してCでコードを記述した回数を数えることさえできないと思います。手元のタスク。はい、それが本当に大きなボトルネックになった場合、私は何かより良いものを見つけたり書いたりするのに苦労しますが、少し比較すると、C++で書いたときに速度が2倍になるのはかなり一般的です。
ただし、少なくとも理論的には、これらすべてがCで間違いなく可能であることを付け加えておきます。言語複雑性理論や計算の理論モデル(チューリングマシンなど)の観点からこれにアプローチする場合、CとC++が同等であることは間違いありません。各関数の特殊なバージョンを作成するのに十分な作業があれば、C ++の場合と同じように、Cでも同じことをすべて理論的に実行できます。
実際のプロジェクトで実際に作成する予定のコードの観点からすると、ストーリーは非常に急速に変化します。実行できることの制限は、ほとんどの場合、合理的に管理できるものになります。表現された計算の理論モデルのようなものではありません。言語によって。Cでほぼ完全に理論的な最適化のレベルは、実用的であるだけでなく、C++では非常に日常的です。
qsort
vsの例でさえstd::sort
無効です。C実装が必要な場合は、インラインバージョンのqsort
instdlib.h
を配置でき、適切なCコンパイラであれば比較関数のインライン化を処理できます。これが通常行われない理由は、それが非常に肥大化しており、パフォーマンス上の利点が疑わしいためです-C++の人々が気にしない傾向がある問題...