Я всегда был не уверен, что означает ключевое слово restrict в C ++?
Означает ли это, что два или более указателя на функцию не перекрываются? Что еще это значит?
Я всегда был не уверен, что означает ключевое слово restrict в C ++?
Означает ли это, что два или более указателя на функцию не перекрываются? Что еще это значит?
restrict
это ключевое слово c99. Да, Рпберт С. Барнс, я знаю, что большинство компиляторов поддерживают__restrict__
. Вы заметите, что все с двойным подчеркиванием, по определению, зависит от конкретной реализации и, следовательно, НЕ от C ++ , а от конкретной версии компилятора.#warning
директива или макросы сигнатур функций (__PRETTY_FUNCTION__
в GCC,__FUNCSIG__
в MSVC и т. Д.).restrict
не считается ключевым словом C ++ (см. en.cppreference.com/w/cpp/keyword ) и фактически является единственным упоминаниемrestrict
в стандарте C ++ 11 (см. open-std.org/jtc1/sc22/wg21 /docs/papers/2012/n3337.pdf , копия FDIS с незначительными редакционными изменениями, §17.2 [library.c], страница PDF 413) гласит, что:restrict
она должна быть исключена из (исключены из, исключены из) сигнатуры и семантики функций стандартной библиотеки C, когда эти функции включены в стандартную библиотеку C ++. Или, другими словами, я констатировал тот факт, что если сигнатура функции стандартной библиотекиrestrict
C содержится в C,restrict
ключевое слово должно быть удалено из сигнатуры эквивалента C ++.Ответы:
В своей статье « Оптимизация памяти» Кристер Эриксон говорит, что хотя он
restrict
еще не является частью стандарта C ++, он поддерживается многими компиляторами, и он рекомендует использовать его, когда это возможно:В компиляторах C ++, которые его поддерживают, он, вероятно, должен вести себя так же, как и в C.
См. Этот пост SO для деталей: Реалистичное использование ключевого слова C99 'restrict'?
Потратьте полчаса, чтобы просмотреть статью Эриксона, это интересно и стоит времени.
редактировать
Я также обнаружил, что компилятор
__restrict__
IBM AIX C / C ++ поддерживает ключевое слово .g ++ также поддерживает это, поскольку следующая программа компилируется чисто на g ++:
Я также нашел хорошую статью об использовании
restrict
:Демистификация ограниченного ключевого слова
Edit2
Я наткнулся на статью, в которой конкретно обсуждается использование restrict в программах на C ++:
Load-hit-store и ключевое слово __restrict
Кроме того, Microsoft Visual C ++ также поддерживает
__restrict
ключевое слово .источник
#ifndef __GNUC__
#define __restrict__ /* no-op */
или что-то подобное. И определить это,__restrict
если_MSC_VER
определено.Как уже говорили другие, если для C ++ 14 ничего не значит , давайте рассмотрим
__restrict__
расширение GCC, которое делает то же самое, что и C99restrict
.C99
restrict
говорит, что два указателя не могут указывать на перекрывающиеся области памяти. Наиболее распространенное использование для аргументов функции.Это ограничивает способ вызова функции, но позволяет оптимизировать компиляцию.
Если вызывающая сторона не выполняет
restrict
договор, неопределенное поведение.Проект C99 N1256 6.7.3 / 7 « Классификаторы типов» гласит:
и 6.7.3.1 «Формальное определение ограничения» дает кровные детали.
Возможная оптимизация
Пример Википедии является очень осветительным.
Наглядно видно, как это позволяет сохранить одну инструкцию по сборке .
Без ограничений:
Псевдо сборка:
С ограничением:
Псевдо сборка:
GCC действительно делает это?
g++
4.8 Linux x86-64:С ними
-O0
они одинаковы.С
-O3
:Для непосвященных соглашение о вызовах :
rdi
= первый параметрrsi
= второй параметрrdx
= третий параметрВывод GCC был даже более ясным, чем статья в вики: 4 инструкции против 3 инструкций.
Массивы
Пока у нас есть единственная экономия инструкций, но если указатель представляет массивы, которые должны быть зациклены, общий случай использования, то можно было бы сохранить группу инструкций, как упомянуто supercat и michael .
Рассмотрим для примера:
Из-за
restrict
этого умный компилятор (или человек) может оптимизировать это так:Что потенциально гораздо более эффективно, так как может быть оптимизировано для сборки при достойной реализации libc (например, glibc). Лучше ли использовать std :: memcpy () или std :: copy () с точки зрения производительности? , возможно с SIMD инструкциями .
Без ограничения эта оптимизация не может быть выполнена, например, рассмотрим:
Тогда
for
версия делает:пока
memset
версия делает:GCC действительно делает это?
GCC 5.2.1. Linux x86-64 Ubuntu 15.10:
Причем
-O0
, оба одинаковы.С
-O3
:с ограничением:
Два
memset
звонка, как и ожидалось.без ограничений: никаких вызовов stdlib, просто развертывание цикла в 16 итераций, которое я не собираюсь воспроизводить здесь :-)
У меня не хватило терпения их тестировать, но я считаю, что ограниченная версия будет быстрее.
Строгое правило алиасинга
restrict
Ключевое слово влияет только указатели совместимых типов (например , дваint*
) , поскольку строгие правила наложения спектров говорят , что сглаживание несовместимых типов не определенно поведение по умолчанию, и поэтому компиляторы могут предположить , что это не произойдет и оптимизирует прочь.Смотрите: что такое строгое правило наложения имен?
Это работает для ссылок?
Согласно документам GCC он делает: https://gcc.gnu.org/onlinedocs/gcc-5.1.0/gcc/Restricted-Pointers.html с синтаксисом:
Существует даже версия для
this
функций-членов:источник
-fno-strict-aliasing
, то неrestrict
должно быть никакой разницы между указателями одного типа или разных типов, нет? (Я ссылаюсь на «Ограничить ключевое слово влияет только на указатели совместимых типов»)restrict
что-то значит в C ++. Если вы вызываете функцию библиотеки C сrestrict
параметрами из программы на C ++, вы должны подчиниться ее последствиям. По сути, еслиrestrict
используется в API библиотеки C, это означает что-то для любого, кто вызывает его с любого языка, включая динамический FFI из Lisp.Ничего. Он был добавлен в стандарт C99.
источник
restrict
как ключевое слово. Следовательно, мой ответ верен. То, что вы описываете, это поведение, специфичное для реализации, и то, на что вы не должны полагатьсяЭто оригинальное предложение добавить это ключевое слово. Как уже отмечалось, это особенность C99 ; это не имеет ничего общего с C ++.
источник
__restrict__
ключевое слово, которое, насколько я могу судить, идентично.restrict
. Поведение программы на C ++ становится неопределенным, если оно нарушает ограничения, подразумеваемыеrestrict
.restrict
ключевое слово. Конечно, если вы передаете псевдонимы-указатели в функцию C, которая объявляет их ограниченными (что вы можете сделать из C ++ или C), тогда они не определены, но это на вас.restrict
. Поведение программы на C ++ становится неопределенным, если оно нарушает ограничения, подразумеваемые restrict. Но это на самом деле не имеет ничего общего с C ++, потому что это «на вас».Там нет такого ключевого слова в C ++. Список ключевых слов C ++ можно найти в разделе 2.11 / 1 стандарта языка C ++.
restrict
это ключевое слово в C99 версии языка C, а не в C ++.источник
__restrict__
ключевое слово, которое, насколько я могу судить, идентично.Поскольку заголовочные файлы из некоторых библиотек C используют ключевое слово, язык C ++ должен будет что-то с этим сделать ... как минимум, игнорируя ключевое слово, поэтому нам не нужно # определять ключевое слово в пустой макрос, чтобы подавить ключевое слово ,
источник
extern C
объявления, либо путем его молча отбрасывания, как в случае с компилятором AIX C / C ++, который вместо этого обрабатывает__rerstrict__
ключевое слово. Это ключевое слово также поддерживается в gcc, поэтому код будет компилироваться в g ++.