2010-12-03 10 views
12

Al ver esta pregunta: Why does a C/C++ compiler need know the size of an array at compile time ? se me ocurrió que los implementadores de compiladores deberían haber tenido algunas veces para mojarse ahora (es parte del estándar C99, eso es hace 10 años) y proporcionar implementaciones eficientes.¿Sobrecarga de la matriz de longitud variable en C++?

Sin embargo, parece que (de las respuestas) se considera costoso.

Esto de alguna manera me sorprende.

Por supuesto, entiendo que una compensación estática es mucho mejor que una dinámica en términos de rendimiento, y a diferencia de una sugerencia, en realidad no haría que el compilador realizara una asignación de montón de la matriz ya que esto probablemente costaría aún más [esto no se ha medido;)]

pero todavía estoy sorprendido por la supuesta costo:

  • si no hay VLA en una función, entonces no habría ni ningún coste, en la medida Puedo ver.
  • si hay un único VLA, entonces uno puede ponerlo antes o después de todas las variables, y por lo tanto obtener un desplazamiento estático para la mayoría del marco de pila (o eso me parece, pero no estoy bien versado en la gestión de pila)

La pregunta surge de múltiples VLA, por supuesto, y me preguntaba si funcionaría una pila de VLA dedicada. Esto significa que un VLA se representaría mediante un conteo y un puntero (de tamaños conocidos, por lo tanto) y la memoria real tomada en un apilamiento secundario solo utilizado para este fin (y, por lo tanto, realmente también una pila).

[reformulando]

¿Cómo se implementan VLA en gcc/VC++?

¿Es realmente tan impresionante el costo?

[reformulación final]

Me parece que sólo puede ser mejor que el uso de, digamos, un vector, incluso con las implementaciones actuales, ya que no se incurre en el costo de una asignación dinámica (a costa de no ser redimensionable).

EDIT:

Hay una respuesta parcial here, sin embargo, que comparan a VLA matrices tradicionales parece injusto. Si supiéramos el tamaño de antemano, entonces no necesitaríamos un VLA. En la misma pregunta, AndreyT dio algunos consejos sobre la implementación, pero no es tan preciso como me gustaría.

+0

@Matthieu M. Eliminado. Debo estar pensando en otra cosa. –

+0

@ Matthieu: piensas que me parece sano ... VLA solo sugiere una sobrecarga cuando hay más de 1 (simplemente colocándolo "después" de elementos de tamaño conocido, y luego podría haber un puntero o ajuste adicional en la pila de compensación conocida para indicar dónde se inician los VLA subsiguientes. Sin embargo, no puedo ver una segunda pila ayudando. –

+0

@Tony: Me preguntaba cómo se implementa la pila, si la implementación significa que solo la parte superior actual de la pila está Conocido, entonces usted tiene un cálculo de desplazamiento dinámico, al parecer, a menos que use una segunda pila para almacenar los elementos VLA. Si conoce tanto la parte superior como la inferior del cuadro actual, entonces para el elemento VLA individual es fácil. De todos modos, ' Simplemente me gustaría saber cómo se hace (actualmente) y cuál es el "costo". –

Respuesta

2

¿Cómo se implementan los VLA en gcc/VC++?

AFAIK VC++ no implementa VLA. Es un compilador de C++ y solo es compatible con C89 (sin VLA, sin restricción). No sé cómo implementa gcc VLA, pero la forma más rápida posible es almacenar el puntero al VLA y su tamaño en la parte estática de la estructura de la pila.De esta forma puede acceder a uno de los VLA con rendimiento de una matriz de tamaño constante (es el último VLA si la pila crece hacia abajo como en x86 (desreferencia [stack puntero + índice * tamaño de elemento + el tamaño de los últimos empujones temporales]), y el primer VLA si crece hacia arriba (desreferencia [indicador de pila de pila + desplazamiento del tamaño de elemento de pila + índice *])). Todos los demás VLA necesitarán una indirección más para obtener su dirección base de la parte estática de la pila.

[Editar : También al usar VLA el compilador no puede omitir el puntero de pila-frame-base, que es redundante, de lo contrario, debido a que todos los desplazamientos desde el puntero de pila se pueden calcular en tiempo de compilación. Entonces tienes un registro gratis menos. — final de edición]

Es el costo realmente tan impresionante?

Realmente no. Además, si no lo usa, no lo paga.

[Editar: Probablemente una respuesta más correcta sería: ¿En comparación con qué? En comparación con un vector asignado de montón, el tiempo de acceso será el mismo, pero la asignación y la desasignación serán más rápidas. — final de edición]

+2

MSVC++ admite restricción (aunque se deletrea '__restrict'). – Crashworks

+0

gracias, pensé que VC++ los apoyaba, mi error. Con respecto a la implementación propuesta, parece que también habría un costo para acceder a las variables locales (es decir, el cálculo dinámico de la compensación), ¿o estoy equivocado? –

+0

@Matthieu: Por supuesto que existe, le cuesta una indirección: '[stack-frame-base-pointer + local-variable-offset]'. Pero no está conectado a VLA. El punto es que para VLA necesitas ** dos ** direcciones indirectas. – ybungalobill

0

Si llegara a ser implementado en VC++, asumiría el equipo compilador utilizar alguna variante de _alloca(size). Y creo que el costo es equivalente al uso de variables con una alineación superior a 8 bytes en la pila (como __m128); el compilador tiene que almacenar el puntero de pila original en alguna parte, y alinear la pila requiere un registro adicional para almacenar la pila desalineada.

Por lo tanto, la sobrecarga es básicamente una indirección adicional (debe almacenar la dirección de VLA en alguna parte) y registrar la presión debido al almacenamiento del rango de pila original en alguna parte también.

Cuestiones relacionadas