Esta guía es la adaptación de un contenido original situado en Ars Technica (Understanding Pipelining Performance), con cuyo permiso contamos para esta publicación.
PUBLICIDAD
Introducción
En computación, se le llama pipeline a una serie de elementos de procesamiento de datos ordenados de tal modo que la salida de cada uno es la entrada del siguiente, como quien dice una cadena de montaje pero en vez de orientada a la manufactura, orientada al procesamiento de datos e instrucciones.
Entender cómo funciona un pipeline es un paso importante para entender qué diablos ocurre dentro de un procesador, y es por eso que en esta guía, que hemos separado en dos capítulos, intentaremos dejarte en claro el sentido y mecánica de estas cadenas de montaje que existen al interior de un CPU.
El material que vas a leer fué licenciado a partir de un documento facilitado por Arstechnica, el cual fué traducido y adaptado por CHW para el mejor entendimiento de nuestro público.
El Pentium 4 y sus pipelines
El Pentium 4 original era un diseño radical por un número de razones, pero quizás su característica más llamativa (y polémica a la vez) era su “pipelining” o “segmentación” extraordinariamente profunda. Con más de 20 etapas, los “pipes” del Pentium 4 eran casi dos veces más profundos que los “pipes” de sus competidores. Recientemente el Prescott, sucesor de los Pentium 4 en 90nm, llevó el “pipelining” a un nivel superior, agregando otras 10 etapas sobre los “pipes” del Pentium 4.
PUBLICIDAD
La estrategia de Intel de profundizar el pipeline del Pentium 4, una práctica que Intel llama “hyperpipelining”, ha dado sus frutos en términos del funcionamiento, pero no sin sus desventajas. En artículos anteriores sobre el Pentium 4 y Prescott, me he referido a las desventajas asociadas a los “pipes” profundos, e incluso he intentado explicar estas desventajas dentro del contexto de artículos técnicos más grandes sobre Netburst y otros asuntos. En la actual serie de artículos, dedicaré bastante tiempo a explicar el “pipelining”, su efecto sobre funcionamiento del microprocesador, y sus desventajas potenciales. Después de una introducción básica sobre el concepto de los “pipes”, explicaré qué se requiere para hacer “pipes” eficientes y qué desventajas presentan diseños con pipelines profundos como el Prescott. Para el final del artículo, debes tener un claro entendimiento de cómo la profundidad de los “pipes” se relaciona con el funcionamiento del microprocesador en diversos tipos de código.
Ciclo de vida de una instrucción
La acción básica de cualquier microprocesador, en tanto se mueve a través de la corriente de instrucciones, se puede descomponer en una serie de cuatro pasos simples, que cada instrucción en la corriente de código debe atravesar para ser ejecutada:
- 1. Fetch: “traer” la instrucción que se va a ejecutar, de la dirección almacenada en el contador de programa.
- 2. Store: “almacenar” la instrucción en el registro de instrucciones y “descifrarla”, incrementando la dirección en el contador de programa.
- 3. Execute: “Ejecutar” la instrucción almacenada en el registro de instrucciones. Si la instrucción no es una instrucción de rama sino una instrucción aritmética, este proceso la envía a la ALU apropiada (ALU: Arithmetic Logic Unit en español: Unidad Aritmético-Lógica), donde el microprocesador: a. “Lee” el contenido de los registros de entrada. b. “Agrega” el contenido de los registros de entrada.
- 4. Write: “Escribir” los resultados de esa instrucción de la ALU nuevamente dentro del registro de destinación
En un procesador moderno, los cuatro pasos arriba descritos son repetidos una y otra vez hasta que el programa termine de ejecutarse. Éstas son, en hecho, las cuatro etapas en un “pipe” clásico del RISC. (Definiré el término “pipe” pronto; por ahora, piensen en un “pipe” como serie de etapas que cada instrucción en la corriente de código debe atravesar cuando se está ejecutando dicha corriente de código.)
Aquí están las cuatro etapas en su forma abreviada, que es la más común y la que verás más a menudo:
- 1. Fetch (Traer)
- 2. Decode (Descifrar)
- 3. Execute (Ejecutar)
- 4. Write (Escribir)
Cada uno de los conceptos anteriores puede ser usado para representar una fase en el “ciclo de vida” de una instrucción. Una instrucción comienza en la fase de “traer”, se mueve a la fase de “descifrar”, después a la fase “ejecutar”, y finalmente a la fase “escribir”. Cada fase toma un tiempo fijo, pero de ningún modo igual al que otra fase toma en cumplir su cometido.
En la mayoría de los ejemplos de procesadores con los que trabajaremos en este artículo, las cuatro fases tomarán la misma cantidad de tiempo; éste no es generalmente el caso en procesadores del mundo real. De cualquier manera, si el procesador simple del ejemplo toma exactamente 1 nanosegundo para terminar cada etapa, entonces el procesador puede acabar una instrucción cada 4 nanosegundos.
Fundamentos del “Pipelining”: una analogia.
Esta sección utiliza una analogía del sistema productivo de una fábrica para explicar el termino “pipelining”. Otras personas utilizan analogías más simples, como lavar la ropa, por ejemplo, para explicar esta técnica, pero hay ciertas razones por las que elegí una analogía más elaborada y más larga para ilustrar cuál es la raíz de este concepto relativamente simple.
Primero, las fábricas basadas en líneas de ensamblaje hacen fácil la visualización, y la imagen mental del proceso se puede elaborar de muchas maneras interesantes, con el fin de exponer una variedad de puntos relacionados. En segundo lugar, y quizás más importante, la gran complejidad de programación que deben enfrentar los diseñadores de la fábrica para ordenar y administrar los recursos tiene análogos directos en la arquitectura de computadores. En muchos casos, los problemas y las soluciones son exactamente iguales, llevadas simplemente a un dominio diferente.
Digamos que mis amigos y yo hemos decidido entrar el negocio de fabricación automotriz, y que nuestro primer producto debe ser un vehículo deportivo para uso general (SUV). Después de cierta investigación, determinamos que hay cinco etapas en el proceso de ensamblaje del SUV:
- Etapa 1: Construir el chasis.
- Etapa 2: Poner el m
otor en el chasis. - Etapa 3: Poner puertas, el capó y las cubiertas en el chasis.
- Etapa 4: Poner las ruedas.
- Etapa 5: Pintar el SUV.
Cada una de las etapas de arriba requiere el uso de trabajadores altamente entrenados con habilidades específicas, y sucede que los trabajadores que son buenos para armar los chasis no saben sobre los motores, carrocería, las ruedas, o pintar, y lo mismo pasa con los constructores de motores, los pintores, y los demás equipos de trabajo. Así que cuando hacemos nuestra primera tentativa de poner una fábrica de SUV, empleamos y entrenamos a cinco equipos de especialistas, uno para cada etapa del proceso de construcción de los SUV. Hay un equipo para construir el chasis, uno para poner el motor, otro para las ruedas, y un equipo para la pintura. Finalmente, siendo los equipos tan especializados y eficientes, cada etapa del proceso de construcción del SUV le toma exactamente una hora a cada equipo.
Ahora, puesto que mis amigos y yo somos simplemente geeks y no ingenieros industriales, teníamos mucho que aprender sobre la fabricación y del uso eficiente de los recursos de la fábrica. Basamos el funcionamiento de nuestra primera fábrica en el siguiente plan: colocamos a los cinco equipos en una línea en el piso de la fábrica, y al comienzo de la línea tenemos al equipo 1 trabajando. Después de que la etapa 1 se completa, el equipo de la etapa 1 pasa la SUV parcialmente terminada al equipo de la etapa 2 y después se van a descansar (para jugar un poco de taca-taca), mientras que el equipo de la etapa 2 construye el motor y lo coloca en el chasis. Una vez que el equipo termina la etapa 2, el SUV pasa a la etapa 3 y el equipo de la etapa 3 asume el control mientras que el equipo de la etapa 2 se une al equipo de la etapa 1 para jugar taca-taca. El SUV pasa por la línea a través de las cinco etapas de esta manera, con solamente un equipo trabajando en cada etapa en cualquier hora dada mientras que el resto de los equipos descansa. Una vez que el SUV terminado acabe la etapa 5, el equipo en la etapa 1 comienza el otro SUV. A este ritmo, toma exactamente cinco horas para acabar un solo SUV, y nuestra fábrica termina un SUV cada cinco horas.
Nos pegamos un salto al futuro de un año. Nuestro SUV, el ChwDelorian LE, se vende como… bueno, se vende como un SUV, lo que significa que le va muy bien. De hecho, se vende tan bien (a pesar de llamarse así) que hemos captado la atención de las FF.AA. y nos ofrecen un contrato millonario para proveer ChwDelorians al Ejército, de manera sostenida y creciente. Las FF.AA. son exigentes, quieren ordenar múltiples ChwDelorians a la vez; puede llegar una orden por 10 ChwDelorians tan fácilmente como una de 500. Mientras más de estas órdenes podamos cumplir por año fiscal, más dinero podremos lavar… ejem!, ganar en ese período, con el resultado de que nuestras hojas de balance ya no parezcan calendario -¡puros números azules desde ahora! Esto, obviamente, significa que tendremos que encontrar una manera de incrementar la cantidad de vehículos que nuestra fábrica puede producir por hora (esto es, nuestra tasa de producción de ChwDelorians). Construir más por hora significa que podemos cumplir los pedidos del Ejército más rápidamente, y eso significa “we can make more money, baby!
La forma más intuitiva para incrementar nuestra tasa de producción sería reducir el tiempo de producción de cada vehículo. Si, ya sea mediante presiones laborales o económicas, lográsemos que nuestros equipos trabajen al doble de velocidad, nuestra fábrica podría producir el doble de vehículos en un mismo tiempo de trabajo. Pero nuestros equipos ya están trabajando tan duro como pueden, así que a menos que haya una irrupción tecnológica que incremente su productividad, ser negreros no es una solución viable.
Sin poder acelerar nuestros equipos, siempre existe la alternativa de usar la fuerza bruta y simplemente inyectar dinero al problema con la construcción de una segunda línea de ensamblaje. Si fuésemos a contratar y entrenar cinco nuevos equipos para formar esta línea, con la misma capacidad de producir un vehículo cada cinco horas, podríamos completar el asombroso total de… ¡Dos! ChwDelorians cada cinco horas el doble de nuestra tasa de producción actual. Pero esto no es muy eficiente en términos del uso de los recursos de la producción, pues no solamente tenemos el doble de equipos trabajando a la vez: también tenemos el doble de equipos usando el taca-taca a la vez y eso sí que es un problema tremendo. Debe haber una manera “más mejol” de hacer las cosas.
Enfrentados a la falta de opciones, contratamos a una consultora para encontrar una manera inteligente de incrementar la producción total de la fábrica sin doblar el número de equipos ni sobreexplotar los actuales. Un año después, y varias lucas mediante, los consultores aparecen con una solución: “¿Por qué deberían nuestros empleados pasarse 4/5 del día jugando taca-taca, tomando cafecito y leyendo Chilehardware, si podrían estar haciendo trabajo útil durante ese tiempo? Con una apropiada programación de los cinco equipos existentes, nuestra fábrica podría completar un ChwDelorian por hora, y así mejorar dramáticamente la eficiencia y el volumen de producción de nuestra línea de ensamblaje. El sistema revisado, se vería más o menos así: el equipo 1 construye un chasis. Una vez que el chasis está completo, lo envían al equipo 2 para que ensamblen el motor, mientras empiezan la construcción de un nuevo chasis. Cuando los equipos 1 y 2 están listos, el trabajo del equipo 2 avanza hacia el equipo 3, el del equipo 1 al equipo 2, y el equipo 1 comienza a construir un nuevo chasis.”
Así, en tanto la línea de ensamblaje comienza a llenarse con vehículos en diferentes etapas de producción, los equipos se ponen a trabajar simultáneamente hasta que todos están trabajando en un vehículo diferente, en diferentes etapas de producción. (Por supuesto, así es como debería ser, para la mayoría de nosotros, una línea de ensamblaje eficiente en la era post-Ford). Si podemos mantener la línea llena, manteniendo a todos los equipos trabajando a la vez, entonces podemos producir un ChwDelorian cada hora: un incremento de 5x sobre la tasa de producción anterior. Eso, mis estimados contertulios, vendría siendo el “pipelining”.
Mientras que el tiempo total consumido en cada etapa de producción no ha cambiado de las 5 horas originales, la tasa a la cual la fábrica como un todo completa los autitos, y por ende la tasa a la cual la fábrica puede cumplir los pedidos del Ejército, ha aumentado drásticamente. El pipelining hace su truco con la optimización total de los recursos existentes. No necesitamos acelerar cada etapa individual del proceso productivo, ni tampoco incrementar descabelladamente la cantidad de recursos que inyectamos al problema; todo lo que necesitamos es obtener más trabajo de los recursos que ya existen.
Volviendo a los microprocesadores, debiera ser fácil el ver cómo este concepto se aplica a las cuatro fases del ciclo de vida de una instrucción. Tal como los propietarios de la fábrica en nuestra analogía querían incrementar el número de ChwDelorians que podían producir en un tiempo det
erminado, los diseñadores de microprocesadores siempre están buscando formas de incrementar el número de instrucciones que un CPU puede completar en un período de tiempo dado. Cuando recordamos que un programa es una secuencia ordenada de instrucciones, se hace claro que incrementar el número de instrucciones ejecutadas por unidad de tiempo es una forma de disminuir el tiempo total de ejecución de un programa. En términos de nuestra analogía, un programa es como una orden de ChwDelorians del Ejército; tal como el incremento de nuestra tasa de producción nos permite completar pedidos más rápidamente, incrementar la tasa de proceso de instrucciones de nuestro procesador (esto es, el número de instrucciones completadas por unidad de tiempo) nos permite correr programas más rápido.
Un ejemplo sin pipelining.
Tiempo atrás, los procesadores sin pipelining trabajaban sobre una instrucción a la vez, moviendo cada instrucción a través de las cuatro fases de su ciclo de vida en el tiempo de un ciclo de reloj. Así, los procesadores sin pipeline se llaman también procesadores de ciclo simple, porque todas las instrucciones toman exactamente un ciclo de reloj para ejecutarse completamente (o, para pasar a través de las cuatro fases de sus ciclos de vida).
Como el procesador completa instrucciones al ritmo de una por ciclo de reloj, queremos que el reloj del CPU corra lo más rápidamente posible, para que la tasa de ejecución de instrucciones del procesador (esto es, el número de instrucciones completadas por nanosegundo) sea tan alta como sea posible. Así necesitamos calcular la mínima cantidad de tiempo que toma completar una instrucción, y hacer el ciclo de reloj equivalente a esa longitud de tiempo. Simplemente pasa que en nuestro caso hipotético de CPU, las cuatro fases del ciclo de vida de la instrucción toman un total de cuatro nanosegundos para completarse, por lo tanto deberíamos setear la duración del ciclo de reloj del CPU a cuatro nanosegundos, así el CPU puede completar todo el ciclo de vida de la instrucción, desde fetch hasta write-back, en un solo ciclo. (Un ciclo de reloj de CPU es simplemente denominado ciclo.)
Figure PIPELINING.4: Procesador de un solo ciclo.
En el diagrama superior, la instrucción azul deja el área de almacenamiento de código entra al procesador, y avanza a través de las fases de su ciclo de vida en el curso del ciclo de cuatro nanosegundos, hasta que el final del cuarto nanosegundo completa la última fase y su ciclo de vida se acaba Sad El fin del cuarto nanosegundo es también el fin del primer ciclo de reloj, por lo tanto ahora que el primer ciclo terminó y la instrucción azul ha completado su ejecución, la instrucción roja puede entrar al procesador al comienzo de un nuevo ciclo de reloj y cruzar el mismo proceso. Esta secuencia de pasos en cuatro nanosegundos se repite hasta que, después de un total de 16ns (o cuatro ciclos de reloj) el procesador ha completado las cuatro instrucciones a un ritmo de 0.25 instrucciones /ns (=4 instrucciones/16ns).
Procesadores de ciclo simple como el de la figura PIPELINING 4 son simples de diseñar, pero desperdician un montón de recursos de hardware. Todo el espacio blanco en el diagrama representa hardware de proceso que permanece inactivo mientras espera que termine de ejecutarse la instrucción actual. Haciendo “pipelining” al procesador, podemos poner a trabajar más de ese hardware en cada nanosegundo, incrementando de esa manera la eficiencia del procesador y su performance en la ejecución de programas.
Antes de seguir, debo clarificar unos cuantos aspectos del diagrama anterior que alguien puede encontrar confusos. Al final del diagrama hay una región nombrada “Completed Instructions” o “instrucciones completadas”. Ahora, las instrucciones completadas se van al limbo una vez que se terminan de ejecutar; después de decirle al procesador como modificar la corriente de datos, son simplemente borradas del procesador. (Nota que las instrucciones que han sido borradas del procesador aún permanecen en el área de almacenamiento de código y están disponibles para su uso repetido.) Entonces la cajita “Completed Instructions” o “instrucciones completadas” al final de la figura PIPELINING.4 no representa una parte real del computador, razón por la cual he puesto una línea punteada a su alrededor. Esta área es sólo un lugar para que mantengamos registro de cuántas instrucciones ha completado el procesador en cierto intervalo de tiempo, o la tasa de ejecución de instrucciones del procesador (o tasa de ejecución, para abreviar), de manera que cuando comparemos diferentes tipos de procesadores tendremos un lugar al cual podremos mirar rápidamente y obtener una impresión instantánea de cuál procesador se desempeña mejor. Mientras más instrucciones complete un procesador en una cantidad de tiempo dada, mejor es su desempeño en los programas, lo cuales son secuencias ordenadas de instrucciones. Así que piensa en la cajita de “instrucciones completadas” como una especie de marcador para registrar la tasa de ejecución de cada procesador, y chequea la cajita en cada uno de los siguientes diagramas para ver cuánto le toma al procesador poblar esta cajita con instrucciones ejecutadas.
Siguiendo con el punto anterior, te puede intrigar por qué la instrucción azul completada en el cuarto nanosegundo no aparece en la cajita “instrucciones completadas” antes del quinto nanosegundo. La razón es simple, y emana de la naturaleza del diagrama: en tanto una instrucción gasta un nanosegundo completo en cada etapa de ejecución, la instrucción azul entra en la fase de escritura al principio del cuarto nanosegundo y termina dicha etapa al final del cuarto nanosegundo. Esto significa que recién en el quinto nanosegundo tenemos completa la instrucción azul. Así, al comienzo del quinto nanosegundo (que coincide con el fin del cuarto) el procesador ha completado una instrucción.
Un ejemplo con pipelining.
Hacer “pipelining” a un procesador significa descomponer su proceso de ejecución de instrucciones lo que hemos estado llamando el “ciclo de vida” de la instrucción- en una serie de etapas discretas de segmentación, que pueden ser completadas en secuencia por hardware especializado. Recuerda la manera en que dividimos el proceso de ensamblaje del vehículo en cinco etapas discretas, con un equipo dedicado asignado al cumplimiento de cada etapa, y tendrás el panorama claro.
En tanto el ciclo de vida de una instrucción consiste en cuatro fases completamente distintas, podemos empezar por descomponer el proceso de ejecución de instrucciones de nuestro procesador de ciclo simple en una secuencia de cuatro etapas discretas de segmentación un pipeline de cuatro etapas-, donde cada etapa corresponde a una fase en el ciclo de vida estándar de la instrucción:
- Etapa 1: Traer la instrucción desde el almacén de código.
- Etapa 2: Decodificar la instrucción.
- Etapa 3: Ejecutar la instrucción.
- Etap
a 4: Escribir los resultados de la instrucción en el archivo de registro.
Observa que nos referimos al número de etapas del pipeline como profundidad del pipeline. Entonces, nuestro pipeline de 4 etapas tiene una profundidad de pipeline igual a 4.
Por conveniencia, digamos que cada una de las cuatro etapas del pipeline anterior toma exactamente un nanosegundo para terminar su trabajo con una instrucción, tal como cada equipo en nuestra línea de ensamblaje demoraba una hora en terminar su porción de trabajo en el vehículo. Entonces nuestro proceso de 4 nanosegundos, en nuestro procesador de ciclo simple, se divide ahora en 4 etapas de pipeline discretas y secuenciales de un nanosegundo de longitud cada una. Ahora observemos otro diagrama para ver cómo un CPU con pipeline ejecutaría las cuatro instrucciones descritas en la figura PIPELINING.4.
Pipeline de 4 etapas
Al comienzo del primer nanosegundo, la instrucción azul entra en la etapa de fetch (traer). Comienza el segundo nanosegundo y la instrucción azul se mueve a la etapa de decodificación mientras la siguiente instrucción, la roja, se abre camino desde el almacén de código al procesador (esto es, entra a la etapa de fetch). Al comienzo del tercer nanosegundo, la instrucción azul avanza a la etapa de ejecución, la instrucción roja a la etapa de decodificación, y la instrucción verde entra a la etapa de fetch. En el cuarto, la instrucción azul avanza a la etapa de escritura, la roja a la de ejecución, la verde a la decodificación, y la violeta a la de fetch. Cuando se ha completado el cuarto nanosegundo y comienza el quinto, la instrucción azul ha pasado a través del pipeline y ha terminado su ejecución. Así podemos decir que al final de cuatro nanosegundos (= a cuatro ciclos de reloj) el procesador con pipeline ha completado una instrucción.
Al comienzo del quinto nanosegundo, el pipeline está completo y el procesador puede empezar a completar instrucciones al ritmo de una instrucción por nanosegundo. Esta tasa de ejecución de 1 instrucción/ns es un incremento de 4x sobre la tasa del procesador de ciclo simple, que era 0.25 instrucciones/ns (o 4 instrucciones cada 16 nanosegundos)
Encogiendo el reloj.
Puedes ver en el diagrama anterior que el rol del reloj del CPU cambia levemente en un procesador con pipeline, versus el procesador de ciclo simple en la figura PIPELINING.4. Como ahora todas las etapas del pipeline deben trabajar simultáneamente y estar listas al comienzo de cada nanosegundo para para pasar los resultados de su trabajo a la siguiente etapa, el reloj es necesario para coordinar la actividad del pipeline completo. La forma en que eso se hace es simple: reducir el tiempo del ciclo de reloj para ajustarse al tiempo que le toma a cada etapa el completar su trabajo, de manera que al comienzo de cada ciclo de reloj las distintas etapas entregan la instrucción en la que estaban trabajando a la siguiente etapa. Como cada pipeline en nuestro procesasdor de ejemplo se toma un nanosegundo en completar su trabajo, podemos setear el ciclo de reloj en un nanosegundo.
Este nuevo método para ajustar el clock del procesador significa que una instrucción nueva no necesariamente se completará al final de cada ciclo, como en el caso del procesador de ciclo simple. En vez de eso, solo al final de aquellos ciclos donde se trabaja en la etapa de escritura, se puede hablar de instrucciones completadas. Los ciclos que tengan la etapa de escritura en blanco no añadirán nuevas instrucciones a la cajita de “instrucciones completadas”, y todo ciclo con una etapa de escritura activa añadirá una nueva instrucción a la caja. Por supuesto, esto significa que al comenzar a trabajar en un programa habrá algunos ciclos de reloj tres para ser exactos- en los cuales no se registrarán instrucciones completadas. Pero una vez que comience el cuarto ciclo, la primera instrucción entrará en la etapa de escritura y el pipeline podrá comenzar a ejecutar nuevas instrucciones en cada ciclo, las cuales tendrán un ritmo de ejecución de 1 instrucción/ns, pues cada ciclo tiene un nanosegundo de longitud.
Encogiendo el tiempo de ejecución de programa.
Observa que el pipelining no cambia el tiempo total de ejecución para cada instrucción individual. Cada instrucción se toma aún 4ns para abrirse camino en el procesador; esos 4ns pueden ser divididos en 4 ciclos e 1ns cada uno o en 1 solo gran ciclo, pero son los mismos 4ns. Así, el pipelining no acelera la velocidad de ejecución de instrucciones, pero acelera el tiempo de ejecución de programas (esto es, el número de nanosegundos que toma un programa completo en ejecutarse) incrementando el número de instrucciones terminadas por unidad de tiempo. Tal como el pipelining en nuestra cadena de ensamblaje de ChwDelorians nos permite completar los pedidos del Ejército en un menor intervalo de tiempo (aún cuando seguimos demorando las mismas 5 horas en ensamblar un vehículo), el pipelining le permite a un procesador ejecutar programas en un tiempo menor aún cuando cada instrucción individual sigue consumiendo el mismo tiempo viajando a través del CPU. El pipelining hace un uso más eficiente de los recursos disponibles del CPU poniendo todas sus unidades a trabajar simultáneamente, permitiéndole de esta forma realizar más trabajo total por cada nanosegundo.
Con esta última explicación concluye la primera parte de nuestra guía… manténganse alerta para la publicación de la segunda parte
Si tienes dudas o sugerencias, escríbelas en este foro