制限を使用する場合としない場合
-
08-07-2019 - |
質問
restrict
の一般的な理解はありますが、細かい点を明確にしたいと思っています。あるバッファーからヌル終了ストリングを読み取り、別のバッファーにURLエンコードされたバージョンを書き出す機能があります。関数には次のシグネチャがあります(現在は restrict
なし):
char const *StringUrlEncode(char const *unencoded,
char *encoded,
char *encodedEnd);
unencoded
は、nullで終わるソース文字列です。宛先バッファーは、 encoded
および encodedEnd
で表されます。 encoded
は、バッファー内の最初の char
を指し、< code> encodedEnd は、バッファの 後の最初の文字を指します。つまり、関数は encodedEnd
が指す場所-これは、C ++ STL規則に精通している場合の基本的な begin
/ end
イテレータペアです。
この関数に restrict
を追加する場合、最初の2つのパラメーターにのみ適用する必要があります。
char const *StringUrlEncode(char const *restrict unencoded,
char *restrict encoded,
char *encodedEnd);
または3つのパラメータすべてに追加することで理解できない利点がありますか?
入力バッファーと出力バッファーを restrict
にすることで、コンパイラーがオーバーラップしないことを知ることができます。しかし、最後のパラメーター encodedEnd
は出力バッファーの終わりをマークするためにのみ使用されるため、 restrict
は実際にはコンパイラーの助けにはならないと考えていますここで(関数宣言に不必要なノイズを追加する以外は、それが害を及ぼさないと思いますが)。
解決
マイクアクトンの記事こちらをお試しください。 Restrictは、使用しないことによるパフォーマンスへの影響と、誤った使用の結果の両方のため、恐ろしいものです。
あなたの場合、3つすべてのポインターに制限を安全に適用できると思われますが、これは同じメモリー領域をエイリアスしないためです。ただし、3番目のポインターで使用しても、パフォーマンス上のメリットはほとんど、またはまったくありません。
他のヒント
この特定のケースでは、 encodedEnd が制限されているかどうかに違いはありません。コンパイラーに unencoded と encoded のエイリアスを作成しないことを約束しているため、読み取りと書き込みが相互に干渉しません。
この場合、restrictが重要である本当の理由は、それがないとコンパイラは encoded を介した書き込みが unencoded を介した読み取りに影響を与えないことを認識できないからです。たとえば、
encoded == unencoded+1
エンコードへの各書き込みは、エンコードされていないからの以降の各読み取りに影響するため、コンパイラは書き込みが完了するまでロードをスケジュールできません。 restrictは、2つのポインターが同じメモリに影響を与えないことをコンパイラーに約束するため、パイプラインのストールを回避するために十分に先にロードをスケジュールできます。
あなたは、それが痛くないことは正しいと思います。ループポインター(pと呼ぶ)は、ループの最後でencodedEndと等しくなります。ただし、ループの後に(pまたはencodedEndから)アクセスする必要はないため、問題にはなりません。 encodedEndから何も書き込まれたり読み込まれたりすることはないので、最適化するものは何もないので、それが助けになるとは思いません。
しかし、最初の2つの制限が本当に役立つはずであることに同意します。