Когда использовать ограничение, а когда нет - PullRequest
23 голосов
/ 07 мая 2009

У меня есть общее понимание restrict, но я надеюсь уточнить некоторые тонкости. У меня есть функция, которая читает строку с нулевым символом в конце из одного буфера и записывает кодированную версию URL в другой буфер. Функция имеет эту подпись (в настоящее время без restrict):

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

unencoded - моя исходная строка с нулевым символом в конце. Целевой буфер представлен encoded и encodedEnd, где encoded указывает на первый char в буфере, а encodedEnd указывает на первый символ после буфера, то есть функции напишет char с, но , не включая местоположение, на которое указывает encodedEnd - это ваша основная пара итераторов begin / end, если вы знакомы с соглашениями C ++ STL.

Если я добавлю restrict к этой функции, ее следует применять только к первым двум параметрам:

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

или есть какая-то польза, которую я не понимаю, добавляя ее ко всем трем параметрам?

Я вижу, что создание входных и выходных буферов restrict помогает компилятору понять, что они не перекрываются. Но так как последний параметр, encodedEnd, используется только для обозначения конца выходного буфера, я думаю, что restrict не поможет здесь компилятору (хотя я предполагаю, что это не повредит , кроме добавления ненужного шума в объявление функции).

Ответы [ 3 ]

12 голосов
/ 07 мая 2009

Попробуйте статью Майка Актона здесь . Ограничение является пугающим из-за влияния на производительность неиспользования и последствий его неправильного использования.

В вашем случае кажется, что вы можете смело применять ограничение ко всем трем указателям, поскольку ни один из них не имеет псевдонима в одной области памяти. Однако при использовании его в качестве третьего указателя выигрыш в производительности будет незначительным или незначительным.

7 голосов
/ 08 мая 2009

В данном конкретном случае не имеет значения, является ли encodedEnd ограниченным или нет; вы пообещали компилятору, что никто не будет псевдонимом без кодировки и с кодировкой , поэтому чтение и запись не будут мешать друг другу.

Реальная причина, по которой ограничение является важной в этом случае, состоит в том, что без него компилятор не может знать, что запись через в кодировке не повлияет на чтение через в незашифрованном виде . Например, если

encoded == unencoded+1

затем каждая запись в в кодировке будет влиять на каждое последующее чтение из в незашифрованном виде , поэтому компилятор не может запланировать загрузку до завершения записи. restrict обещает компилятору, что два указателя не влияют на одну и ту же память, поэтому он может планировать загрузки достаточно далеко вперед, чтобы избежать остановок конвейера.

4 голосов
/ 07 мая 2009

Я думаю, вы правы, что это не повредит. Ваш указатель цикла (назовите его p) будет равен encodedEnd в конце цикла. Но ничего не нужно делать после цикла (из p или encodedEnd), так что это не должно быть проблемой. Я тоже не думаю, что это поможет, потому что ничего не пишется и не читается из encodedEnd, поэтому нет ничего, что можно было бы оптимизировать

Но я согласен с тем, что первые два ограничения должны действительно помочь.

...