{"id":1689,"date":"2024-03-11T16:06:43","date_gmt":"2024-03-11T15:06:43","guid":{"rendered":"https:\/\/intsight.com\/?p=1689"},"modified":"2024-03-12T14:27:13","modified_gmt":"2024-03-12T13:27:13","slug":"destruccion-creativa","status":"publish","type":"post","link":"https:\/\/intsight.com\/index.php\/2024\/03\/11\/destruccion-creativa\/","title":{"rendered":"Destrucci\u00f3n creativa"},"content":{"rendered":"<p><span style=\"font-variant: small-caps; font-size: 107%;\">El compilador de Austra<\/span> sigue mejorando. Y la librer\u00eda tambi\u00e9n, que todo hay que decirlo.<\/p>\n<p>Finalmente, he podido a\u00f1adir generaci\u00f3n de valores aleatorios con AVX2, adem\u00e1s de la que ya hab\u00eda implementado con AVX512. La dificultad resid\u00eda en la necesidad de rotar circularmente un entero largo. AVX512 te da la instrucci\u00f3n. Pero es f\u00e1cil ver que en AVX2 es posible hacer lo mismo con dos desplazamientos l\u00f3gicos y una conjunci\u00f3n l\u00f3gica.<\/p>\n<p>El otro avance importante es la vectorizaci\u00f3n del algoritmo de Box-Muller para generar distribuciones normales. Ya ten\u00edamos un logaritmo natural para vectores de 256 y de 512 bits. Ahora a\u00f1adimos una funci\u00f3n que calcula simult\u00e1neamente el seno y el coseno para estos dos tipos de vectores. De hecho, hay una variante especial que es la que usa Box-Muller, en la que todos los valores est\u00e1n entre cero y dos veces pi, y es un poco m\u00e1s r\u00e1pida. A\u00f1ad\u00ed esta funci\u00f3n, la utilic\u00e9 en el c\u00f3digo del generador normal y, finalmente, se ha usado en las clases de vectores, matrices y secuencias.<\/p>\n<h4>Operaciones in situ<\/h4>\n<p>El compilador intenta ahora optimizar expresiones como la siguiente:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-linenumbers=\"false\">\nvector1 + vector2 + vector3\n<\/pre>\n<p>\u00bfQu\u00e9 hay aqu\u00ed para optimizar? A primera vista, parecer\u00eda que esa expresi\u00f3n es candidata para reescribirse mediante un combinador lineal, que de hecho existe y se usa para algunas optimizaciones ya:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-linenumbers=\"false\">\nvec([1, 1, 1, vector1, vector2, vector3)\n<\/pre>\n<p>Se podr\u00eda utilizar, pero este constructor a\u00f1adir\u00eda tres multiplicaciones escalares innecesarias. Lo que s\u00ed nos ahorrar\u00edamos ser\u00eda la creaci\u00f3n de dos b\u00faferes temporales como resultado de las dos sumas de la expresi\u00f3n original. Lo que ha aprendido a hacer el compilador es a modificar la expresi\u00f3n original a este otro patr\u00f3n, que es m\u00e1s general:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-linenumbers=\"false\">\n(vector1 + vector2).InplaceAdd(vector3)\n<\/pre>\n<p><code>InplaceAdd<\/code> no se puede llamar directamente desde el lenguaje: es una instrucci\u00f3n peligrosa, porque sobrescribe el b\u00fafer del primer operando. El compilador tiene que detectar que el primer operando es de tipo temporal, y no va a utilizarse en el resto de la f\u00f3rmula, o en el peor de los casos, en el resto de la sesi\u00f3n. Pero en el ejemplo mostrado, la primera suma es evidentemente una construcci\u00f3n temporal, independientemente del sitio de donde estemos sacando las tres variables usadas.<\/p>\n<p>Naturalmente, podemos hacerlo mejor si ya sabemos qu\u00e9 son <code>vector1<\/code> y sus dos amigos. Si son variables de sesi\u00f3n, no hay nada m\u00e1s que podamos hacer. Lo mismo ocurre si son par\u00e1metros de una funci\u00f3n definida por el usuario o variables locales, introducidas por una cl\u00e1usula <code>let<\/code>. Pero supongamos que la expresi\u00f3n original fuese la siguiente:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-linenumbers=\"false\">\nvec::random(10) + vector2 + vector3\n<\/pre>\n<p>En ese caso, el primer operando se crea en un constructor y s\u00f3lo se usa en esa expresi\u00f3n. El compilador puede entonces crear el siguiente c\u00f3digo equivalente:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-linenumbers=\"false\">\nvec::random(10).InplaceAdd(vector2).InplaceAdd(vector3)\n<\/pre>\n<p>No importa de d\u00f3nde salgan <code>vector2<\/code> y <code>vector3<\/code>. El b\u00fafer del primer operando puede ser reutilizado, y eso es lo que hacemos. El resultado de <code>InplaceAdd<\/code>, dicho sea de paso, tambi\u00e9n se puede sobrescribir con total seguridad.<\/p>\n<p>Este tipo de optimizaciones es mejor que las haga un compilador, y no la librer\u00eda. Es el compilador quien tiene toda la informaci\u00f3n sobre el uso de un operando. De momento, nos movemos sobre terreno seguro. Hay algunas operaciones que podr\u00edan optimizarse con este truco, pero de momento no lo hacemos. Por ejemplo, si una variable local s\u00f3lo se utiliza una vez, no hay memoria compartida que tengamos que respetar. De momento, no contamos el n\u00famero de usos de cada variable local.<\/p>\n<p>Finalmente, hemos ampliado las optimizaciones que hac\u00edamos sobre vectores reales a vectores complejos. Es un poco m\u00e1s de c\u00f3digo, pero no se hace m\u00e1s lenta la compilaci\u00f3n.<\/p>\n<blockquote style=\"font-size:85%\"><p>Se supone que la se\u00f1orita de la imagen es Freya bailando sobre calaveras. Eran Kali y Shiva quienes practicaban este tipo de danza, pero estaba seguro de que la t\u00eda que la IA iba a generar para Freya iba a ser m\u00e1s guapa. \u00bfY las calaveras? Pues est\u00e1n debajo. Pero los generadores de Inteligencia Artificial siguen teniendo problemas para generar manos humanas. De hecho, la imagen que utilizo para Austra la llamo en mi cabeza \u00abla chica del eccema\u00bb. Llevo meses haciendo retoques a sus manos, y todav\u00eda tienen problemas. Pero me gusta el tono del pelo, el \u00f3valo facial y la postura. No se puede tener todo.<\/p><\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>El compilador de Austra sigue mejorando. Y la librer\u00eda tambi\u00e9n, que todo hay que decirlo. Finalmente, he podido a\u00f1adir generaci\u00f3n de valores aleatorios con AVX2, adem\u00e1s de la que ya hab\u00eda implementado con AVX512. La dificultad resid\u00eda en la necesidad de rotar circularmente un entero largo. AVX512 te da la instrucci\u00f3n. Pero es f\u00e1cil ver [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1690,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[92],"tags":[65,15,73,90,26],"class_list":["post-1689","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-austra","tag-net","tag-algorithms","tag-austra","tag-functional-programming","tag-vector"],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/intsight.com\/wp-content\/uploads\/2024\/03\/freya.png?fit=500%2C500&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/posts\/1689","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/comments?post=1689"}],"version-history":[{"count":17,"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/posts\/1689\/revisions"}],"predecessor-version":[{"id":1707,"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/posts\/1689\/revisions\/1707"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/media\/1690"}],"wp:attachment":[{"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/media?parent=1689"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/categories?post=1689"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/tags?post=1689"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}