26

大まかな理解はしていますが、restrictいくつかの細かい点を明確にしたいと思っています。あるバッファから null で終わる文字列を読み取り、別のバッファに URL エンコードされたバージョンを書き出す関数があります。関数には次のシグネチャがあります (現在は なしrestrict):

char const *StringUrlEncode(char const *unencoded, 
                            char *encoded,
                            char *encodedEnd);

unencoded私のヌル終了ソース文字列です。encoded宛先バッファはandで表されますencodedEnd。ここで、 はバッファ内encodedの最初のものを指し、バッファのの最初の charを指します。つまり、関数はsを書き込みますが、 が指す場所は含みません。これは基本的な/イテレータです。 C++ STL 規則に精通している場合は、ペアにしてください。charencodedEndcharencodedEndbeginend

この関数に追加restrictする場合、最初の 2 つのパラメーターにのみ適用する必要があります。

char const *StringUrlEncode(char const *restrict unencoded, 
                            char *restrict encoded,
                            char *encodedEnd);

または、3つのパラメーターすべてに追加することで理解できない利点がありますか?

入力バッファーと出力バッファーを作成するとrestrict、それらがオーバーラップしていないことをコンパイラーが認識するのに役立つことがわかります。しかし、最後のパラメーター ,encodedEndは出力バッファーの末尾をマークするためにのみ使用されるため、restrictここでコンパイラーにとって実際には何の助けにもならないと思います (ただし、不要なノイズを追加する以外は、害はないと思いますが)関数宣言に)。

4

3 に答える 3

12

こちらの Mike Acton の記事(古いリンク) をお試しください。Restrict を使用しない場合のパフォーマンスへの影響と、誤って使用した場合の結果の両方から、Restrict は恐ろしいものです。

あなたの場合、同じメモリ領域にエイリアスがないため、3つのポインターすべてに制限を安全に適用できるように思えます。ただし、3 番目のポインターで使用しても、パフォーマンス上の利点はほとんどまたはまったくありません。

于 2009-05-07T05:49:33.950 に答える
7

この特定のケースでは、encodedEndがrestrictであるかどうかに違いはありません。誰もエンコードされていない、またはエンコードされているエイリアスを作成しないことをコンパイラに約束したので、読み取りと書き込みが互いに干渉することはありません。

この場合、restrictが重要である本当の理由は、それがないと、コンパイラーは、エンコードされた書き込みがエンコードされていない読み取りに影響を与えないことを認識できないためです。たとえば、

encoded == unencoded+1

その場合、エンコードされたものへの各書き込みは、エンコードされていないものからの後続の各読み取りに影響を与えるため、コンパイラーは、書き込みが完了するまでロードをスケジュールできません。制限は、2つのポインターが同じメモリーに影響を与えないことをコンパイラーに約束するため、パイプラインストールを回避するために十分に先にロードをスケジュールできます。

于 2009-05-07T23:56:18.317 に答える
4

痛くないというのは正しいと思います。ループ ポインター (p と呼びます) は、ループの最後で encodedEnd と等しくなります。しかし、ループの後に (p または encodedEnd から) 何もアクセスする必要がないため、問題にはなりません。また、encodedEnd から何も書き込まれたり読み取られたりしないため、最適化するものは何もないため、それが役立つとは思いません。

しかし、最初の 2 つの制限が本当に役立つことに同意します。

于 2009-05-07T05:35:15.093 に答える