まず第一に、関数が本当に時間に敏感でない限り、過度に最適化しようとしないでください。提供されたものを使用してください。正確性を確認するのは簡単で、スマートになろうとはしません。
関数を本当に高速にする必要がある場合は、さらに最適化する方法がたくさんあります。多くの、本当に多くの方法。それらのいくつかは、文字列の特定のメモリ レイアウトを期待または想定しています (たとえば、文字列は単語境界に割り当てられ、割り当ては常に単語境界までパディングされます)。したがって、アルゴリズムはプロセッサ、コンパイラ、およびメモリ アロケータの一部の組み合わせで機能し、他の組み合わせでは惨めに失敗する可能性があるため、注意が必要です。
念のために、文字カウンターを高速化するいくつかの可能な方法をリストします。
- 文字列を単語 (32 ビットまたは 64 ビット整数) ずつ読み取ります。L1キャッシングと投機的/順不同の実行のおかげで、必ずしも多くの助けにはなりません. これには、最後のワードのループ終了調整が必要です (NUL ターミネータの後のバイトのカウントミス)。ワード アラインされ、パディングされたメモリ アロケータでのみ使用します。
- 条件を削除し、代わりに (配列への) すべての文字のカウントを計算し、必要な文字のカウントを返します。(これにより条件が削除され、文字列の長さが事前にわかっている場合は、優れたループ展開が可能になり、条件分岐の 1 つのポイントが削除されます。)
- 文字列の長さが事前にわかっている場合 (別の場所で計算されている)、それを使用してループを展開できます。または、for ループとして記述し、適切な #pragma とコンパイラ オプションを適用して、コンパイラにループ展開を行わせるようにすることをお勧めします。
- ルーチンをアセンブラで記述します。この方法に進む前に、すべてのコンパイラーの最適化を開始し、最初にルーチンを逆アセンブルします。コンパイラーが、知っているすべての潜在的なトリックと、知らなかったいくつかのトリックを既に使用していることに気付くでしょう。
- 文字列が潜在的に非常に大きい (メガバイト) 場合 (ここでは推測しています)、OpenCL/CUDA 経由でグラフィックス カードを使用すると、潜在的な可能性があります。
等々。
しかし、実際に問題が発生した場合は、お持ちのものを使い続けることをお勧めします. これがおもちゃの問題であり、それを楽しむために最適化している場合は、先に進んでください。
サイクル シェービングは、CPU と命令セットを学習する楽しい方法ですが、プログラミング タスクの 99.999999...% では、努力する価値はありません。