¿Hay algún inconveniente en asignar una gran cantidad de la pila para una sola matriz en un sistema embebido?

12

Por lo general, no tengo problemas para decidir si algunos datos deben ser globales, estáticos o en la pila (no hay asignación dinámica aquí, por lo que no se debe usar el montón). También he leído algunas preguntas y respuestas como esta, pero mi pregunta es más específica, ya que implica una gran cantidad de datos, en comparación con la memoria del sistema.

Estoy trabajando en un código existente que trato de mejorar (diseño, posibles problemas, actuaciones, etc.). Este código se ejecuta en una antigua MCU de 8 bits con solo 4KB de RAM . En este código, me enfrento al uso de una matriz de casi 1 KB (sí, 1 KB en un sistema de RAM de 4KB ). Se utiliza cada byte de esta matriz, esa no es la cuestión. El problema es que esta matriz es una matriz estática en el archivo donde se declara, por lo que su ciclo de vida es el mismo que el del programa (es decir, puede considerarse infinito).

Sin embargo, después de leer el código, descubrí que esta matriz no necesita un ciclo de vida infinito, está construida y tratada de manera totalmente procesal, por lo que deberíamos poder declararla solo en la función donde se usa, de esta manera estaría en la pila y, por lo tanto, ahorraríamos este 1 KB de RAM.

Ahora la pregunta: ¿sería una buena idea? Desde el punto de vista del diseño, si no necesita un ciclo de vida infinito / global, pertenece a la pila. Pero bueno, eso es 1KB de 4KB, ¿no hay ningún inconveniente en asignar el 25% de la RAM de esta manera? (eso podría ser el 50% o más de la pila)

¿Podría alguien compartir alguna experiencia con este tipo de situación, o alguien piensa en alguna razón válida para no poner esta matriz en la pila? Estoy buscando inconvenientes técnicos, así como comentarios sobre el diseño.

Lo único que tengo en cuenta es que tengo que asegurarme de tener 1 KB de pila libre al ingresar a esta función. Tal vez eso es todo lo que tengo que cuidar, tal vez no.

Tim
fuente
44
Usted escribió "y, por lo tanto, guarde este 1 KB de RAM". ¿Guardarlo para qué? Ese 1 KB debe estar disponible cuando lo necesite para la matriz, ¿por qué no hacer una asignación estática? ¿Tiene otro uso para la memoria cuando no es necesaria para la matriz?
kkrambo
@kkrambo En algún momento consideramos que un sistema está lleno cuando no podemos agregar nada más en la RAM, ya sea algo estático o en la pila. Si colocamos esta matriz en la pila solo cuando la usamos, dejaría lugar para otra funcionalidad siempre que no se usen al mismo tiempo. Pero la pregunta es totalmente legítima, por el momento si no cambiamos nada en el SW, no necesitamos más RAM;)
Tim
1
¿Podría aclarar si esta matriz tiene contenido que siempre permanece igual o si cambia cuando se invoca la función que la usa?
Blrfl
@Blrfl Cambia cada vez que se llama a la función.
Tim

Respuestas:

8

Lo único que tengo en cuenta es que tengo que asegurarme de tener 1 KB de pila libre al ingresar a esta función.

Sí, y esa es una fuerte restricción. Es mejor estar seguro estáticamente que tener un espacio tan grande disponible en la pila. Si el código es pequeño, si está utilizando un GCC reciente para compilar su código, vea esto .

Por cierto, algunos microprocesadores baratos pueden utilizar un marco de llamada "grande" más costoso que uno "normal" (por ejemplo, porque su conjunto de instrucciones favorecería un desplazamiento de un byte desde el puntero de la pila). YMMV.

Además, si está codificando en C y siente que su gran matriz puede reutilizar su espacio para otros fines, podría considerar convertirla en un miembro de la unión (con una variable global de uniontipo). Sí, eso es bastante feo.

Alternativamente, podría considerar la codificación de un asignador de almacenamiento dinámico primitivo adecuado para su aplicación (y podría tener una API diferente de malloc& free....).

Basile Starynkevitch
fuente
1
Gracias, en realidad esperaba un poco este tipo de respuesta, es decir, mantenerlo estáticamente asignado para asegurarme de que no termine con un desbordamiento de pila. Lamentablemente no tengo un compilador GCC reciente y el código no es pequeño.
Tim
¿No puede obtener (quizás compilando GCC a partir de su código fuente) un compilador GCC para su plataforma?
Basile Starynkevitch
2
Ya tengo uno, es muy viejo. Trabajar en uno nuevo no está en mi alcance, ni encajaría en mi horario. Pero claro, algunas cosas serían más fáciles con herramientas actualizadas.
Tim
3
Pedirle a su jefe que le consiga un GCC más nuevo (ya sea proporcionándole herramientas binarias actualizadas o dándole tiempo para la recompilación de GCC) vale la pena en mi humilde opinión, porque es muy probable que un GCC más nuevo se optimice un poco mejor (¿lo sabe gcc -flto -Os? ) y podrías ganar algo de memoria ...
Basile Starynkevitch
2
Está en camino, pero eso no llegará antes de un tiempo. Ya uso -Os en otros sistemas con cadenas de herramientas más recientes, pero no estaba al tanto de este parámetro -flto, gracias por señalarlo. (Tenga en cuenta que he hecho algunas pruebas con GCC -Os y -O1-3 hace unas semanas en GCC 5.4.1 y la RAM era la misma todo el tiempo. Sin embargo, el tiempo de ejecución de FLASH y MCU fue diferente. Eso no estaba en el mismo MCU que el que menciono en este Q / A)
Tim
6

Las personas tienden a ser cautelosas con una pila grande, porque crece hacia atrás en la RAM y sobrescribe los valores de las variables, lo que conduce a un comportamiento inexplicable. Se pone aún peor, porque necesita conocer la dirección de puntero de pila más baja posible y restar el tamaño para asignar al ingresar a la rutina.

Todo esto es un trabajo para la gestión de la memoria del hardware (debe generar trampas o fallas cuando se produce un desbordamiento de la pila) o para el compilador, dado que tiene características para este tipo de análisis.

De lo contrario, puede hacer lo que quiera con su RAM.

Martin Sugioarto
fuente
4

Como las respuestas anteriores han señalado, también recomendaría primero dejar la matriz estática si se ajusta a la memoria. En la mayoría de los casos, es mucho más importante tener una huella de memoria determinista, incluso si eso significa que "desperdicia" memoria para variables que no se usan todo el tiempo. Poner matrices grandes en su pila lo sobrará con demasiada facilidad, y los desbordamientos de la pila tienden a causar problemas difíciles de encontrar y de reproducir (si no puede usar MMU para proteger la pila).

La sugerencia de compartir el bloque con algunos otros datos con union es válida para la OMI, aunque también puede ser fuente de problemas difíciles de encontrar, si localiza variables incorrectas en ella.

Si se está quedando sin memoria y necesita desesperadamente crear variables de vida más corta para compartirlo, antes de mover la matriz a la pila, consideraría agregar una asignación de memoria dinámica, aunque tenga sus propios inconvenientes. En este caso, podría no ser una respuesta, ya que la matriz suena bastante grande en comparación con la memoria disponible.

MaKo
fuente
1

Tienes otra opción si tienes algún tipo de almacenamiento flash. Puede cambiar la velocidad de acceso por ram almacenando sus datos en flash y leyendo y buscando allí. Solo necesitaría cargar un registro a la vez en ram. Será un poco más complicado si necesita poder actualizar los registros. Necesitará un mecanismo segmentado de nivelación de desgaste. He hecho esto en el pasado e incluí un índice para acelerar el acceso.

Tereus Scott
fuente
1
También he hecho esto en el pasado, pero mi pregunta fue más sobre los problemas que podría enfrentar si pongo esto en la pila, no sobre las alternativas a la RAM cuando nos faltan. Gracias por responder de todos modos
Tim
1

Especialmente cuando trabajas con sistemas embebidos, quieres que ocurran la mayor cantidad de fallas posibles en el momento de la compilación y nada falla en el tiempo de ejecución (aunque sería bueno si pudiéramos lograr esto, sin embargo ...).

Hacer matrices grandes que pueda necesitar en estados arbitrarios de su programa asignados estáticamente hace exactamente eso: el enlazador eventualmente le advertirá "esto no encaja en la RAM", mientras que la asignación de la pila simplemente haría que su programa se bloquee con la pila difícil de depurar desbordamientos

tofro
fuente