何时使用限制,何时不使用
我对 restrict
有一个大致的了解,但我希望澄清一些要点。 我有一个函数,可以从一个缓冲区读取以 null 结尾的字符串,并在另一个缓冲区中写出 URL 编码版本。 该函数具有以下签名(当前没有 restrict
):
char const *StringUrlEncode(char const *unencoded,
char *encoded,
char *encodedEnd);
unencoded
是我的以 null 结尾的源字符串。 目标缓冲区由 encoded
和 encodedEnd
表示,其中 encoded
指向缓冲区中的第一个 char
,< code>encodedEnd 指向缓冲区之后的第一个字符,即该函数将写入char
,但不包括 encodedEnd
指向的位置——如果您熟悉 C++ STL 约定,这就是基本的 begin
/end
迭代器对。
如果我将 restrict
添加到此函数,它是否应该仅应用于前两个参数:
char const *StringUrlEncode(char const *restrict unencoded,
char *restrict encoded,
char *encodedEnd);
或者将其添加到所有三个参数是否有一些我不理解的好处?
我可以看到,对输入和输出缓冲区进行限制可以帮助编译器知道它们不会重叠。 但由于最后一个参数 encodedEnd
仅用于标记输出缓冲区的结尾,我认为 restrict
对编译器实际上没有任何帮助这里(尽管我认为除了向函数声明添加不必要的噪音之外,它不会造成任何伤害)。
I have a general understanding of restrict
but I'm hoping to clarify some fine points. I have a function that reads a null-terminated string from one buffer and writes out a URL encoded version in another buffer. The function has this signature (currently without restrict
):
char const *StringUrlEncode(char const *unencoded,
char *encoded,
char *encodedEnd);
unencoded
is my null-terminated source string. The destination buffer is represented by encoded
and encodedEnd
, where encoded
points to the first char
in the buffer and encodedEnd
points to the first char after the buffer, i.e. the function will write char
s up to but not including the location pointed to by encodedEnd
-- this is your basic begin
/end
iterator pair if you're familiar with C++ STL conventions.
If I add restrict
to this function, should it only be applied to the first two parameters:
char const *StringUrlEncode(char const *restrict unencoded,
char *restrict encoded,
char *encodedEnd);
or is there some benefit I'm not understanding by adding it to all three parameters?
I can see that making the input and output buffers restrict
helps the compiler know that they don't overlap. But since the last parameter, encodedEnd
, is only used to mark the end of the output buffer, I'm thinking that restrict
wouldn't really be any help to the compiler here (though I assume it wouldn't hurt, other than adding unnecessary noise to the function declaration).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
请尝试此处 (旧链接)。 限制是可怕的,因为不使用它会对性能产生影响,而且使用不正确也会产生后果。
在您的情况下,听起来您可以安全地对所有三个指针应用限制,因为没有一个别名是相同的内存区域。 然而,在第三个指针上使用它几乎没有任何性能优势。
Try Mike Acton's article here (old link). Restrict is frightening because of both the performance implications of not using it and the consequences of using it incorrectly.
In your case, it sounds like you could safely apply restrict to all three pointers as none alias the same memory area. However there is going to be little to no performance benefit from using it on the third pointer.
在这种特殊情况下,encodedEnd 是否受到限制并没有什么区别; 您已向编译器承诺,没有人使用 unencoded 和 encoded 别名,因此读取和写入不会相互干扰。
在这种情况下,限制很重要的真正原因是,如果没有它,编译器就无法知道通过编码进行的写入不会影响通过未编码进行的读取。 例如,如果
每次对编码的写入都会影响对未编码的后续读取,那么编译器就无法安排加载,直到写入完成。 limit 向编译器保证两个指针不会影响同一内存,因此它可以提前足够远的时间安排加载以避免管道停顿。
In this particular case it won't make a difference whether encodedEnd is restrict or not; you have promised the compiler that no one aliases unencoded and encoded, and so the reads and writes won't interfere with each other.
The real reason that restrict is important in this case is that without it the compiler can't know that writes through encoded won't affect reads through unencoded. For example, if
then each write to encoded would affect each subsequent read from unencoded, so the compiler can't schedule the load until the write has completed. restrict promises the compiler that the two pointers don't affect the same memory, so it can schedule loads far enough ahead to avoid pipeline stalls.
我认为你是对的,它不会伤害。 您的循环指针(称为 p)将等于循环末尾的encodedEnd。 但是在循环之后不需要访问任何内容(从 p 或encodedEnd),所以这应该不是问题。 我认为这也没有帮助,因为没有从encodedEnd写入或读取任何内容,因此没有什么可以优化的。
但我同意你的观点,前两个限制应该确实有帮助。
I think you're right that it wouldn't hurt. Your loop pointer (call it p) will equal encodedEnd at the end of the loop. But nothing need be accessed after the loop (from either p or encodedEnd), so that shouldn't be a problem. I don't think it will help, either, because nothing is ever written or read from encodedEnd so there's nothing to optimize away.
But I agree with you having the first two restrict should really help.