Aplicaciones Numéricas que desafían los conceptos sobre el desarollo de lenguajes
David Cardozo
int main() {
long x = 1e16;
double y = 1e16;
long z = x+1;
printf("%d\n", x == y);
printf("%d\n", y == z);
printf("%d\n", x == z);
return 0;
}
Supongamos d es un diccionario
d[1] = "Adelante"
¿Que deberían devolver las siguientes búsquedas de diccionario?
d[1.0]
d[1 + 0im]
d[2//2]
¿¿¿???
¿¿¿???
¿¿¿???
irb(main):001:0> d = {};
irb(main):002:0> d[1] = "Adelante"
=> "Adelante"
irb(main):003:0> d[1.0]
=> nil
Sin embargo
irb(main):001:0> 1 == 1.0;
=> true
>>> d = {}
>>> d[1] = "Adelante"
>>> d[1.0]
'Adelante'
>>> from cmath import *
>>> d[1+0j]
d = Dict();
d[1] = "Adelante"
juliaa> d[1.0]
"Adelante"
julia> d[1 + 0im]
"Adelante"
julia> d[2//2]
"Adelante"
En Julia 0.2 hasheamos números con diferentes tipos de manera diferente:
d = Dict()
d[1] = "Adelante"
d[1.0] = "ECOOP" # <- diferente entrada
julia> d
Dict{Any,Any} with 2 entries:
1.0 => "ECOOP"
1 => "Adelante"
¿Que ocurre si limitamos los tipos del diccionario?
d = Dict{Int,String}()
d[1] = "Adelante"
d[1.0] = "ECOOP" # <- ¿Que debería hacer esto?
Dos opciones
Mismo codigo trabaja diferente dependiendo del tipo de la llave
Hashear números por valor
hash(x::Float64) = 3h(x) + h(trunc(Int64, x))
hash(x::Int64) = 3h(convert(Float64, x)) + h(x)
Hasheo eficiente por valor para Float64 y Int64
h es alguna función para hashear 64 bits
¿Y para otros tipos?
La función descomposición es el punto donde (con valores reales) tipos numéricos que soportan hasheo se integran con el protocolo de hasheo
$$ num \cdot \frac{2^{pod}}{den} $$
Hashing es entonces definido genéricamente en términos de estos 3 valores
descomposicion(x) debería retornar tres valores enteros: num, pod, den
Permitir al programador generar código en varios puntos del proceso de compilación
Código
Fuente
AST
Lexing
Parsing
AST
tipeado
Inferencia de tipos
Código
nativo
Generación de
código
Macros
JIT
funciones generadas
Evaluar
macro horner(x, p...)
ex = esc(p[end])
for i = length(p)-1:-1:1
ex = :(muladd(t, $ex, $(esc(p[i]))))
end
Expr(:block, :(t = $(esc(x))), ex)
end
@foo a + b
@foo b + a
i.e no se pueden usar macros como argumentos a funciones de alto nivel
Generación de código automática
Guardada para reuso (GC)
Tener un lenguaje de alto nivel que se pueda trabajar interactivamente
= fácil desarrollo, prototipado, exploración
=> lenguaje dinámicamente tipeado
Mucho software de donde escoger: Python, Matlab / Octave, R, Scilab
Históricamente, no podemos escribir codigo crítico de rendimiento ("lazos internos") en estos lenguajes... debemos cambiar a C/Fortran/... (estáticos).
[e.g SciPy git master es ~70% C/C++/Fortran]
Trabajable, pero Python → Python+C = un gran salto en complejidad
Esto implica en depender en librerías externas maduras operando en grandes bloques de datos para codigo crítico de rendimiento
¡Buen Consejo! Pero...
Mucho progreso en compiladores JIT gracias a aplicaciones web & JIT ofrecido por herramientas de software libre como LLVM
Javascript en navegadores modernos alcanza velocidades como C
Muchos esfuerzos, se han dado para aumentar la velocidad de lenguajes dinámicos, e.g PyPy, Numba / Cython
¿Que pasaría si un lenguaje dinámico fuera designado para JIT desde el principio, con el objetivo de ser alto-nivel mientras esté en la velocidad de C?
(y es mucho más fácil llamar SciPy desde Julia que desde PyPy)
Julia está escrito casi 70% en Julia
funciones especiales s(x): problema clásico que no puede ser vectorizado... cambiar de varios polinomios que dependen en x
Muchas de las funciones especiales en Julia vienen de las librerías usuales C/Fortran pero algunas están escritas en Julia.
Julia erfinv(x)
3-4x mas rápido que Matlab y 2-3x más rápido que SciPy
Julia polygamma(m,z)
2 más rápido que SciPy (C/Fortran) para reales y además soporta argumento complejo
Julia erfinv(x)
3-4x mas rápido que Matlab y 2-3x más rápido que SciPy
Julia polygamma(m,z)
2 más rápido que SciPy (C/Fortran) para reales y además soporta argumento complejo
Código de Julia puede ser incluso mas rápido que código optimizado de C/Fortran utilizando técnicas de metaprogramación que son difíciles en lenguajes de bajo nivel