Siempre estaba inseguro, ¿qué significa la palabra clave restringir en C ++?
¿Significa que los dos o más punteros dados a la función no se superponen? ¿Qué más significa?
c++
restrict-qualifier
Estera
fuente
fuente

restrictes una palabra clave c99. Sí, Rpbert S. Barnes, sé que la mayoría de los compiladores son compatibles__restrict__. Notará que cualquier cosa con guiones bajos dobles es, por definición, específica de implementación y, por lo tanto, NO C ++ , sino una versión específica del compilador.#warningdirectiva común o las macros de firma de funciones (__PRETTY_FUNCTION__en GCC,__FUNCSIG__en MSVC, etc.).restrictno se considera una palabra clave de C ++ (consulte en.cppreference.com/w/cpp/keyword ), y de hecho, la única menciónrestricten el estándar C ++ 11 (consulte open-std.org/jtc1/sc22/wg21 /docs/papers/2012/n3337.pdf , una copia del FDIS con pequeños cambios editoriales, §17.2 [library.c], PDF página 413) establece que:restrictse debe omitir (excluir, excluir) de las firmas y semánticas de la función de biblioteca estándar de C cuando esas funciones se incluyen en la biblioteca estándar de C ++. O en otras palabras, dije el hecho que dice que si la firma de una función de biblioteca estándar de C contienerestrictC, larestrictpalabra clave debe eliminarse de la firma del equivalente de C ++.Respuestas:
En su artículo, Memory Optimization , Christer Ericson dice que mientras
restricttodavía no forma parte del estándar C ++, que es compatible con muchos compiladores y recomienda su uso cuando esté disponible:En los compiladores de C ++ que lo admiten, probablemente debería comportarse igual que en C.
Vea esta publicación SO para más detalles: Uso realista de la palabra clave 'restringir' C99?
Tómese media hora para leer el papel de Ericson, es interesante y vale la pena.
Editar
También descubrí que el compilador AIX C / C ++ de
__restrict__IBM admite la palabra clave .g ++ también parece admitir esto ya que el siguiente programa se compila limpiamente en g ++:
También encontré un buen artículo sobre el uso de
restrict:Desmitificando la palabra clave restringida
Edit2
Me encontré con un artículo que analiza específicamente el uso de restrict en los programas de C ++:
Load-hit-stores y la palabra clave __restrict
Además, Microsoft Visual C ++ también admite la
__restrictpalabra clave .fuente
#ifndef __GNUC__#define __restrict__ /* no-op */o similar. Y definirlo a__restrictsi_MSC_VERestá definido.Como otros dijeron, si no significa nada a partir de C ++ 14 , entonces consideremos la
__restrict__extensión GCC que hace lo mismo que el C99restrict.C99
restrictdice que dos punteros no pueden apuntar a regiones de memoria superpuestas. El uso más común es para argumentos de función.Esto restringe cómo se puede llamar a la función, pero permite más optimizaciones de compilación.
Si la persona que llama no sigue el
restrictcontrato, comportamiento indefinido.El C99 N1256 borrador 6.7.3 / 7 "Calificadores de tipo" dice:
y 6.7.3.1 "Definición formal de restricción" da los detalles sangrientos.
Una posible optimización
El ejemplo de Wikipedia es muy esclarecedor.
Muestra claramente cómo, ya que permite guardar una instrucción de ensamblaje .
Sin restricción:
Pseudo ensamblaje:
Con restringir:
Pseudo ensamblaje:
¿GCC realmente lo hace?
g++4.8 Linux x86-64:Con
-O0, son lo mismo.Con
-O3:Para los no iniciados, la convención de convocatoria es:
rdi= primer parámetrorsi= segundo parámetrordx= tercer parámetroLa salida de GCC fue incluso más clara que el artículo wiki: 4 instrucciones vs 3 instrucciones.
Matrices
Hasta ahora, tenemos ahorros en una sola instrucción, pero si el puntero representa las matrices que se van a recorrer, un caso de uso común, entonces se podrían guardar un montón de instrucciones, como lo mencionaron supercat y michael .
Considere por ejemplo:
Debido a que
restrictun compilador inteligente (o humano), podría optimizar eso para:¿Qué es potencialmente mucho más eficiente, ya que puede ser ensamblado optimizado en una implementación decente de libc (como glibc) ¿Es mejor usar std :: memcpy () o std :: copy () en términos de rendimiento? , posiblemente con instrucciones SIMD .
Sin, restringir, esta optimización no podría hacerse, por ejemplo, considere:
Entonces la
forversión hace:mientras que la
memsetversión hace:¿GCC realmente lo hace?
GCC 5.2.1.Linux x86-64 Ubuntu 15.10:
Con
-O0ambos son lo mismo.Con
-O3:con restricción:
Dos
memsetllamadas como se esperaba.sin restricción: no hay llamadas stdlib, solo un desenrollamiento de bucle ancho de 16 iteraciones que no pretendo reproducir aquí :-)
No he tenido la paciencia para compararlos, pero creo que la versión restringida será más rápida.
Regla de alias estricta
La
restrictpalabra clave solo afecta a punteros de tipos compatibles (por ejemplo, dosint*) porque las estrictas reglas de alias dicen que el alias de tipos incompatibles es un comportamiento indefinido por defecto, por lo que los compiladores pueden asumir que no sucede y optimizar.Ver: ¿Cuál es la estricta regla de alias?
¿Funciona para referencias?
De acuerdo con los documentos de GCC, sí lo hace: https://gcc.gnu.org/onlinedocs/gcc-5.1.0/gcc/Restricted-Pointers.html con sintaxis:
Incluso hay una versión para las
thisfunciones miembro:fuente
-fno-strict-aliasing, entonces norestrictdebería haber diferencia entre punteros del mismo tipo o tipos diferentes, no? (Me refiero a "La palabra clave restringir solo afecta a punteros de tipos compatibles")restrictsignifica algo en C ++. Si llama a una función de biblioteca C conrestrictparámetros de un programa C ++, debe obedecer las implicaciones de eso. Básicamente, sirestrictse usa en una API de biblioteca C significa algo para cualquiera que lo llame desde cualquier lenguaje, incluido el FFI dinámico de Lisp.Nada. Fue agregado al estándar C99.
fuente
restrictcomo una palabra clave. Por lo tanto, mi respuesta es correcta. Lo que describe es un comportamiento específico de implementación y algo en lo que realmente no debe confiar.Esta es la propuesta original para agregar esta palabra clave. Sin embargo, como se señaló puntualmente, esta es una característica de C99 ; No tiene nada que ver con C ++.
fuente
__restrict__palabra clave que es idéntica por lo que puedo decir.restrict. El comportamiento del programa C ++ se vuelve indefinido si viola las restricciones implicadas porrestrict.restrictpalabra clave. Por supuesto, si pasa punteros con alias a una función C que los declara restringidos (lo que puede hacer desde C ++ o C), entonces no está definida, pero eso depende de usted.restrict. El comportamiento del programa C ++ se vuelve indefinido si viola las restricciones implicadas por restrict. Pero esto en realidad no tiene nada que ver con C ++, porque está "en ti".No existe tal palabra clave en C ++. La lista de palabras clave de C ++ se puede encontrar en la sección 2.11 / 1 del estándar de lenguaje C ++.
restrictes una palabra clave en la versión C99 del lenguaje C y no en C ++.fuente
__restrict__palabra clave que es idéntica por lo que puedo decir.Dado que los archivos de encabezado de algunas bibliotecas C usan la palabra clave, el lenguaje C ++ tendrá que hacer algo al respecto ... como mínimo, ignorando la palabra clave, por lo que no tenemos que #definir la palabra clave en una macro en blanco para suprimir la palabra clave .
fuente
extern Cdeclaración, o se descarta silenciosamente, como es el caso con el compilador AIX C / C ++, que en su lugar maneja la__rerstrict__palabra clave. Esa palabra clave también es compatible con gcc para que el código compile lo mismo con g ++.