miércoles, mayo 31, 2006

Rayo de luz

Quicker than a ray of light I'm flying...
Madonna
Como existe el riesgo de aburrir con este tema, voy a ser lo más breve posible. He vuelto a probar una traducción del código de XSight RT a Delphi 7 (nativo, por supuesto). Resultado: tiempos de ejecución casi idénticos, para la versión nativa y para .NET. Sorprendente, ¿verdad?
Esta vez he sido muy cuidadoso con la eficiencia y la calidad del código en Delphi: nada de tipos de interfaz, nada de funciones que devuelvan estructuras, modificación in situ de vectores y colores siempre que sea posible...
¿A qué se puede deber esta vez que no logre más velocidad en Delphi, creando una aplicación nativa? Mi teoría es que tiene que ver con el modelo del procesador. Cuando XSight RT para .NET se ejecuta en mi portátil, el compilador JIT genera código para el Sempron que hace de CPU. Eso implica, por ejemplo, que para copiar un valor de tipo Double, se puede utilizar un registro MMX. Esto lo he comprobado personalmente analizando el código nativo final. En Delphi 7, sin embargo, no existe soporte para CPU's posteriores al Pentium "clásico" (no sé si en las versiones más modernas se permite al compilador usar conjuntos de instrucciones extendidos, pero sospecho que no). Como consecuencia, para copiar un Vector, cada uno de sus tres componentes debe copiarse mediante cuatro instrucciones, usando registros de 32 bits.
Este es un problema importante, que he empezado a ver desde otra óptica. Supongamos, por ejemplo, que aparece una versión de Delphi nativo (o de C++ Builder nativo, o de cualquier otro lenguaje) que, efectivamente, permitiese seleccionar estos conjuntos especiales de instrucciones al compilar... ¡como hace Visual C++ en modo "nativo"! Si quisiéramos aprovechar esa opción, tendríamos que crear tantas versiones de la aplicación como conjuntos de instrucciones incompatibles existen ahora mismo. La aplicación tendría una versión diferente para Pentium y para Athlon, y quizás una versión "legacy" para máquinas viejas. Con .NET, este problema no existe, y lo mejor de todo es lo que acabo de comprobar experimentalmente: la calidad del código generado por el compilador JIT puede ser mejor que la generada por un compilador nativo si no tomamos medidas especiales.
¿Significa esto que XSight RT puede parangonarse ahora mismo con otros ray tracers que funcionan en modo nativo? Probablemente sí. Entonces, ¿por qué me he estado rompiendo el coco todo este tiempo para mejorar la velocidad de ejecución? El problema es que XSight RT implementa una extensión del algoritmo básico de ray tracing llamada informalmente distributed ray tracing. Hablando en plata, el algoritmo extendido implementa trucos especiales para lograr efectos como la distancia focal, la reflexión difusa, etc. Muchos de los ejemplos que utilizo para benchmarks especifican que por cada píxel se lancen de 36 a 144 rayos... aunque muchas veces no sea necesario para obtener la calidad de imagen deseada. Resumiendo: estoy forzando XSight RT, a propósito, para que trabaje más de lo necesario.

13 Comments:

Anonymous Nico said...

El proyecto FastCode hace algo parecido a lo que dices. Son unas librerías que detectan la CPU y usan rutinas optimizadas. Si te instalas el Delphi Speedup de Hausladen, te parcheará la RTL (también en Delphi 7) y el mismo IDE irá mucho más rápido.

Delphi 2006 incorpora algunas de esas mejoras, por ejemplo un gestor de memoria diferente. En cualquier caso, siempre es posible usar las librerías de FastCode y tener detección de CPU y distintas instrucciones, un sistema que me parece más interesante que elegir la CPU al compilar. Con FastCode tienes una sola versión del programa.

jueves, junio 01, 2006 8:53:00 a. m.  
Anonymous Alfredo said...

Otra cosa que hay que tener en cuenta es que hay bastante gente trabajando para mejorar el compilador JIT de Microsoft mientras que el futuro de compiladores nativos como el de Delphi es bastante incierto. Sobre todo cuando se generalice el uso de sistemas operativos de 64 bits.

Yo he migrado a C# una aplicación que comencé en Delphi y ahora funciona bastante más rápidamente, sobre todo si se juega un poco con el recolector de basura y se lanza cuando la aplicación está desocupada. Hacer algo parecido con Delphi sería mucho más trabajoso. Yo creo que la ganancia de velocidad puede venir en buena parte de suprimir cientos y cientos de bloques try finally.

Supongo que la diferencia de velocidad entre Delphi y C# dependerá bastante del tipo de aplicación.

jueves, junio 01, 2006 1:43:00 p. m.  
Blogger Ian Marteens said...

El proyecto FastCode hace algo parecido a lo que dices.

Hum, tiene buena pinta. Pero, ¿no tendrá problemas con el bit NX? ¿O es algo estático?

Lo del gestor de memoria ya lo había leído. En realidad, hay productos comerciales de este tipo para C a puñados. El propio CLR tiene dos garbage collectors diferentes: uno para aplicaciones en el servidor, y otro para aplicaciones GUI.

Otra cosa que hay que tener en cuenta es que hay bastante gente trabajando para mejorar el compilador JIT de Microsoft

Es increíble la cantidad de gente "conocida" en el mundo académico que hace o ha hecho investigación para Microsoft. Eso es lo normal: que cuando funcione un negocio, haya pasta y las cosas avancen. Delphi, si ya con lo que hay tiene problemas para mantenerse al día, no quiero pensar cuándo podrá compilar código para Itanium, que exige condiciones muy especiales al código ejecutable.

Sobre los try/finally: en este caso, no los hay, prácticamente. El código en C# se preparó primero para evitar pedir memoria todo lo posible, y para sacar objetos de una caché si era necesario (en el modelo actual, no lo es). Ese fue el primer gran recorte de tiempo de ejecución: todo lo que se pueda, a una caché. En Java sería aún peor, porque aquí al menos los struct te evitan crear y destruir pequeños objetos todo el tiempo. Por otra parte, al tratarse básicamente de código matemático, no hay acceso a otros tipos de recursos que haya que devolver, al menos en el núcleo de la aplicación.

Lo que he hecho esta vez es congelar dos copias de los dos proyectos, y simplificarlas al máximo. Si a alguien, en algún momento, le pica la curiosidad, que me de un toque y le envío el ejemplo.

Para mí, lo importante de todo esto, es certificar que "managed", cuando se refiere a .NET, no implica necesariamente "lento". Es verdad que cuesta ajustar bien el código, porque tienes que haberte formado primero un modelo muy exacto de lo que está pasando por debajo... pero no es imposible. Y si en algún momento me diese por crear un producto comercial a partir de este prototipo, me iría directamente a Visual C++, o quizás al compilador de Intel para C/C++.

Incluso ahí tengo dudas: la gente de POV Ray dice que utilizan el compilador de Intel para generar las versiones precocinadas, porque les proporciona más velocidad que compilar con Visual C++ (clásico, of course). Sin embargo, hace poco hice una prueba compilando con Visual C++ el código completo de POV Ray, y toqué las opciones de compilación (eliminar stack frames, generar código post-Pentium, etc, etc)... y la copia que obtuve del ejecutable va ligeramente más rápido que la versión que distribuyen compilada con Intel.

viernes, junio 02, 2006 4:50:00 a. m.  
Anonymous Nico said...

Hum, tiene buena pinta. Pero, ¿no tendrá problemas con el bit NX? ¿O es algo estático?

Incluye los fuentes, así que puede verse cómo parchea. Por otra parte, si el bit NX es el atributo de ejecución del bloque de memoria lo único que hay que hacer es activarlo. Lo tengo hecho para generar un salto y es trivial. De todas formas, para lo que te ocupa sólo tendrías que compilar el proyecto con FastCode y, mejor aun, Delphi 2006 y ver si hay cambios. No es muy deportivo usar una versión del compilador de hace cuatro años.

Respecto a recolectores de memoria, también los hay para Delphi. Por cierto, que en Mundo Delphi saqué un artículo sobre constructores en Delphi contando cómo quitarse completamente el problema cuando toma la forma de muchos objetos pequeños.

Las comparaciones de rendimiento suelen ser muy divertidas cuando, como estás haciendo ahora, se basan en la práctica (en vez de afirmaciones teóricas) porque siempre es posible optimizar un poco más cada una de las partes.

Es verdad que el esfuerzo llega a superar lo que uno está dispuesto a hacer para un programa "normal". Pero es mucho más frecuente encontrarte cuellos de botella de lo que la gente piensa. En esos momentos agradeces estar trabajando sobre una herramienta que te permite remangarte y bajar de nivel. Por eso me gustan tan poco las máquinas virtuales, tal como se suelen entender. Están pensadas para atrapar clientes, no para solucionar ningún problema real.

Y eso de las dificultades que vaya a tener Delphi con las nuevas arquitecturas no lo compro. Hay proyectos voluntarios como Free Pascal que compilan para cuatro. Por no hablar de la GCC, OCAML y familia. ¿Por qué iba a tener problemas una empresa refundada con decenas de millones?

viernes, junio 02, 2006 11:30:00 a. m.  
Blogger Ian Marteens said...

:) ¿Decenas de millones... de dólares, o de colaboradores? ¿Ha aparecido ya el misterioso comprador de la DevCo? Lo que yo digo sobre Delphi es que, efectivamente, hay más talento ahora mismo fuera de Borland que dentro. Y eso no es normal. Claro, las cosas pueden evolucionar de varios modos, y es arriesgado adelantarse a hacer pronósticos (en un sentido y en el otro).

No es muy deportivo usar una versión del compilador de hace cuatro años.

:) Tampoco es muy deportivo cobrar una pasta todos los años por casi lo mismo. O que me traten de vender como "herramienta para .NET v2.0" una herramienta que sólo compila (y con sudores) para .NET v1.1. Yo, como empresario, no me atrevo a algo así: por eso no hubo una Cara Oculta de Delphi 7, ni una Cara Oculta de C# 2. Para añadir dos párrafos por capítulo y volver a cobrar el precio completo del libro, para eso tenemos ya a Borland. La diferencia entre los precios de primera compra y los de actualización de esta gente es ridícula.

Por eso, aunque me parece estupendo que haya gente que siga haciéndole gratis el trabajo a Borland, un servidor no está dispuesto a seguir pasando por el aro. Mientras tenga que pagar, quiero respeto por mi dinero.

Las comparaciones de rendimiento suelen ser muy divertidas cuando, como estás haciendo ahora, se basan en la práctica (en vez de afirmaciones teóricas) porque siempre es posible optimizar un poco más cada una de las partes.

Más que divertidas, yo las llamaría "complicadas". ¿Sabías que la licencia de usuario de Delphi prohibe publicar benchmarks sobre "the Product"? He estado dudando un día antes de publicar este post por las implicaciones legales. Y me he atrevido a hacerlo cuando he interpretado que "the Product" es el IDE de Delphi, y que lo que prohiben es medir cuán rápido compila éste, no la velocidad de ejecución de los programas compilados. Pero vete a saber cuál era la intención de los abogados...

De todos modos, las diferencias en calidad de código se asumen que no deben existir, o al menos, como gesto de buena voluntad debería asumirse, ¿no? En cualquier caso, como al final a Santo Tomás lo hicieron santo, el código de los dos proyectos está disponible para quien comprobarlo con sus propios ojos.

viernes, junio 02, 2006 12:50:00 p. m.  
Blogger SHArQ said...

cita:
"Para añadir dos párrafos por capítulo y volver a cobrar el precio completo del libro, para eso tenemos ya a Borland."

Y a Marco Cantù, y a Steve Teixeira... :)

viernes, junio 02, 2006 1:29:00 p. m.  
Blogger Ian Marteens said...

:) Bueno, por decir algo en defensa de esta gente (como escritores, porque como técnicos no lo necesitan), hay que reconocer que tienen una desventaja que no tengo yo: tienen una editorial por detrás que es la que determina cuándo y cómo publican. Menda, que es un lobo solitario, se evita estas tragedias, aunque tiene que apechugar con otras en compensación (el precio final tiene que ser necesariamente mayor, las distribuidoras te ignoran..). Pero la verdad es que me alegro por haber tomado este camino.

viernes, junio 02, 2006 1:57:00 p. m.  
Blogger SHArQ said...

De todas maneras y si no estoy equivocado, la cantidad de literatura dedicada a Delphi ha bajado drásticamente en estos últimos años... hasta el punto que creo que para D2005 sólo salió UN libro en castellano, y las traducciones que habitualmente se hacían de los libros en inglés (muy pocos actualmente también) me parece que brillan por su ausencia.

Esto, quieras que no, también acaba por "matar" un lenguaje.

Si Delphi tuviese la mitad (¡qué digo la mitad! ¡la cuarta parte!) de literatura que tiene Java... otro callo cantaría, creo yo.


Saludos

PS: Perdón por el off-topic :)

viernes, junio 02, 2006 2:10:00 p. m.  
Anonymous Nico said...

:) ¿Decenas de millones... de dólares, o de colaboradores? ¿Ha aparecido ya el misterioso comprador de la DevCo? Lo que yo digo sobre Delphi es que, efectivamente, hay más talento ahora mismo fuera de Borland que dentro.

Ayer escribí un poco sobre el presente de Delphi. Para resumir: Delphi no peligra fuera de Borland. Es dentro donde estaba desapareciendo. Hay suficientes datos sobre el proceso de compra para afirmar que el precio será más de cien millones. Si te vas a gastar esa cifra, al menos unas decenas adicionales irán en inversión.

Por eso, aunque me parece estupendo que haya gente que siga haciéndole gratis el trabajo a Borland, un servidor no está dispuesto a seguir pasando por el aro.

Coincido completamente. Y lo mismo ocurre con el 95% de la clientela. Por eso muchos estamos tan contentos de que Borland vaya a desaparecer de nuestra vista.

Más que divertidas, yo las llamaría "complicadas". ¿Sabías que la licencia de usuario de Delphi prohibe publicar benchmarks sobre "the Product"?

Me atrevería a decir que esa licencia en España no vale el papel en que está escrita y en cualquier caso sólo hay que mirar el historial del grupo de news b.p.d.non-technical para ver que se han publicado resultados y debatido extensamete. Algunos sacaron el tema de la licencia, y recibieron la respuesta obvia: una cosa es Delphi y otra muy diferente tus propios programas. Borland no puede prohibirte medir el rendimiento de lo que escribes. En todo caso (y repito que en España sería mucho pedir) la velocidad del compilador mismo.

De todos modos, las diferencias en calidad de código se asumen que no deben existir, o al menos, como gesto de buena voluntad debería asumirse, ¿no?

Por supuesto que no hablo de ninguna diferencia intencionada, sobre todo por tu parte. Pero cuando se han publicado este tipo de comparaciones con código siempre han aparecido correcciones: muchos pares de ojos ven más que dos.

viernes, junio 02, 2006 2:56:00 p. m.  
Blogger Ian Marteens said...

Tranqui, aquí no hay off-topics.

Tal vez la solución para la literatura en Delphi sea la autoría colectiva. No tengo claro que funcionase: la experiencia que tengo con esos libros escritos por tropecientos autores (en la difunta Wrox, por ejemplo) no es muy buena. Pero puede ser que sólo se trate de un único ingrediente que falte en la mezcla. Lo de Wrox lo digo porque, cuando empecé a interesarme en .NET, se me ocurrió comprar unos cuantos de los libros que estaba publicando Wrox... y ahí están acumulando polvo. También hay que decir que Wrox debía tener alguna relación con la industria óptica, porque te podías quedar ciego leyendo dos libros impresos con las letritas minúsculas de esa gente.

Hay un experimento que quiero hacer hacer tiempo, en relación con esto de la autoría colectiva, pero vas a ver enseguida qué los tiros van en otra dirección: mi idea es un wiki sobre estructuras de datos y algoritmos. Supongo que los habrá en inglés, y que ya habrán páginas en castellano: por eso mismo no quiero hacerlo yo solo, para poder cubrir todas las áreas razonables. Por ejemplo, ahora estoy usando mucho (otra vez) algoritmos y ee.dd. de geometría computacional: kd-trees, algoritmos con segmentos, diagramas de Voronoi, etc, etc.

viernes, junio 02, 2006 2:56:00 p. m.  
Blogger Ian Marteens said...

Por supuesto que no hablo de ninguna diferencia intencionada, sobre todo por tu parte.

Lo siento, a veces me entra la vena paranoica. De todos modos, es de mi propio interés sacar la conclusión más exacta de este asunto: eso podría decidir si merece la pena convertir un prototipo en una aplicación "seria" o no.

(te tengo que dar un toque por email, pero por otro motivo; luego miro en tu blog a ver si encuentro tu email; si no, dame un toque a mi email en IntSight).

Como información en general a quienes estén leyendo, que sepáis que en España hay mucha gente trabajando en este tipo de proyectos. Incluso he encontrado referencias a una empresa en Internet que mantiene una aplicación propia de generación de imágenes, aunque basada (al parecer) en un algoritmo llamado Metropolis Light Transport (Metropolis es o fue un matemático que inventó esa técnica para problemas de integración numérica por los años 50). Y hay mucha gente en América Latina que también se dedica a esto: nombres y apellidos que se ves cómo se repiten en artículos, referencias en Internet e incluso libros.

Es un área de desarrollo muy "agradecida", la verdad, porque los resultados "se ven".

viernes, junio 02, 2006 3:05:00 p. m.  
Anonymous Nico said...

El correo es nico y el dominio espira.net.

viernes, junio 02, 2006 3:59:00 p. m.  
Anonymous Alfredo said...


Hay un experimento que quiero hacer hacer tiempo, en relación con esto de la autoría colectiva, pero vas a ver enseguida qué los tiros van en otra dirección: mi idea es un wiki sobre estructuras de datos y algoritmos. Supongo que los habrá en inglés, y que ya habrán páginas en castellano: por eso mismo no quiero hacerlo yo solo, para poder cubrir todas las áreas razonables.


Si que hay varios wikibooks en inglés, aunque lo que visto es bastante básico.

Para algoritmos más avanzados y estudios en profundidad tienes CiteSeer y Google Academic.

Yo no le veo mucho sentido a escribir sobre algoritmos avanzados en español. Casi nadie lo hace.

viernes, junio 02, 2006 4:03:00 p. m.  

Publicar un comentario

<< Home