HispaMSX

De vuelta On-topic: OPTIMIZACION

2004-05-14 10:18:52
Citando a Martin Korth, autor de los emuladores NO$MSX y NO$GMB, entre otros, en ensamblador y para Windows (!): "Optimization dies. Only heros live forever".

En cualquier caso, y antes de arrancarnos la carne de los huesos, como programador tengo que decir que "optimizar", ya optimizan y mucho los buenos compiladores profesionales actuales. El problema de "ineficiencia" al que os referís, tiene que ver con un problema de arquitectura más que de programación: hay que conseguir que un montón de elementos de hardware completamente diferentes actúen frente al programa de un modo análogo, y esto sólo se consigue sacrificando rendimiento máximo. Es el mismo problema de Java, aunque se enfoque de una forma diferente.

De todas maneras, no creo que la comunidad del MSX sea la más adecuada para criticar la falta de optimización de los programas, mientras se obstina en programar en BASIC, lo que claramente desaprovecha las capacidades de nuestras maquinitas. De todos modos, lo importante no es la optimización, sino que el producto resultante sea atractivo. Los juegos de Imanok y de MSXKun son muy buenos, tienen una calidad fantástica y un buen diseño: no necesitan manejar la CPU al 100%. El problema es diferente: el diseño debe primar. Y os lo está diciendo un programador...

Siguiendo con el tema de la optimización, hay que matizar algún aspecto. Optimizar es conseguir la mejor solución posible en una variable. Por tanto, antes de avanzar en la idea de optimización, hay que elegir qué queremos optimizar: velocidad de ejecución, tamaño resultante del programa, utilización de RAM... El problema radica en que en MSX no se puede ni se debe optimizar una única componente, sino alcanzar un equilibrio entre las tres, porque en general, tanto la memoria como la velocidad de proceso están muy limitadas.

Aquí es cuando empiezan los problemas. Ejemplo muy básico, de andar por casa.

Volcado de RAM a VRAM - distintas perspectivas

1.-Uso la BIOS y me despreocupo: casi no ocupa espacio, pero es MUY LENTO.

LD HL,ORIGEN_RAM
LD DE,DESTINO_VRAM
LD BC,NUM_BYTES
CALL LDIRVM

En total, esto ocupa unos 12 bytes y funciona bien. Pero te permite copiar muy pocos datos por interrupción, lo que puede resultar grave para desarrollar un juego con una fuerte carga gráfica (digamos, con scroll).

2.-Reprogramo la BIOS y consigo algo que funciona mejor y puede ser un poco más rápido.

LD HL,ORIGEN_RAM
LD DE,DESTINO_VRAM
LD BC,NUM_BYTES
CALL MI_RUTINA_1

MI_RUTINA_1:
; Y esto no está muy optimizado, lo estoy programando "para que funcione"
; Hacemos que el puntero a VRAM del VDP esté donde queremos
DI
LD A,E
OUT [99h],A
LD A,D
OR 40h
OUT [99h],A
; Hacemos algún apaño
LD E,C
LD C,98h
; Empezamos el proceso de copia
BUCLE:
OTIR ; Copia datos
DEC E
JR NZ,BUCLE
; Y ya está
EI
RET

Es labor del programador saber cuándo se pueden mandar datos a la VRAM. Recomiendo hacerlo después de la interrupción de V-BLANK, que es cuando más "traga" la VRAM. Es decir, cuando tiene un mayor ancho de banda disponible.

NOTA: quizás se me haya colado algún error, porque estoy escribiendo esto de memoria. Si está mal, que alguien me corrija, por favor. WYZ?

3.-Sólo apto para freaks: rutina de copia super-rápida para psicópatas y demosceners.

El truco está en que la instrucción OTIR es MUY LENTA y hace muchas comparaciones que son innecesarias. Crearemos una nueva versión, más rígida, que ocupa mucha más memoria, pero que se acerca mucho más al límite teórico de transferencia:

RUTINA_RAPIDA:
; Parámetros: HL- origen de datos en RAM
                  DE - destino de datos en
                  C - número de bloques de 256 bytes a copiar
; Vamos allá. El principio es idéntico
DI
LD A,E
OUT [99h],A
LD A,D
OR 40h
OUT [99h],A
; Hacemos algún apaño
LD E,C
LD C,98h
; Empezamos el proceso de copia
BUCLE:
OUTI
OUTI
OUTI
..... (habría que repetir esta misma instrucción 256 veces seguidas!)
DEC E
JR NZ,BUCLE
; Ya está
EI
RET

Bueno, aparte de perder flexibilidad, puesto que aquí copiamos en bloques de 256 bytes como mínimo, lo cierto es que esta rutina es mucho más rápida, puesto que OUTI tarda únicamente 4 ciclos por dato.

Siendo un tanto optimista, podríamos copiar con una rutina como ésta bastantes datos. Aun así, nunca os recomendaría (por pura prudencia) copiar más de 1 KB o de 1,5 KB por interrupción, puesto que hay que tener en cuenta que a 60 Hz las cosas son más difíciles que a 50 Hz, es decir, no se dispone de menos tiempo de v-blank y, por tanto, se pueden copiar menos datos. Para psicópatas en activo a los que no les preocupe trabajar SIEMPRE a 50 Hz, imagino que se podrían alcanzar los 2 KB, aunque raspando. Como comprenderéis, esta rutina es adaptable para que, siendo bastante rápida, soporte tamaños menores y ocupe menos espacio de programa. Por ejemplo, repetir 32 veces la instrucción OUTI en lugar de 256 puede ser un equilibrio razonable entre velocidad y tamaño de programa.

Vaya, menudo sermón os acabo de endosar. Espero que no me lo tengáis en cuenta. Si a alguno de los editores de revistas les interesa, pueden publicar este mini-artículo, o rogarme/pagarme/comprarme para que haga uno un poco más extenso y con más detalles al respecto.

A todos, un saludo. NapalMSX, con esta sabiduría concentrada pueden hacerse demos que se muevan bastante bien en MSX...

Eduardo Robsy

_________________________________________________________________
¿Dónde se esconden l@s solter@s? Encuentra miles de perfiles en MSN Amor & Amistad. http://match.msn.es/


<Anterior en la conversación] Conversación actual [Siguiente en la conversación>