Opinion sobre los array en Python
Hernan Foffani
hernan en orgmf.com.ar
Mar Abr 20 13:16:17 CEST 2004
Antonio:
>>> Yo sigo pensando que la implementacion de array en el propio
>>> lenguaje es posible y deseable. Es cierto que he subestimado la
>>> importancia del coste
>>> de funcionamiento de python como interprete que es muy alto, pero
>>> ese es
>>> un precio que tiene sentido pagar. Creo que aunque existan partes
>>> importantes que no se pueden optimizar hay otras muchas que si. La
>>> discusión se centra en si los arrays se pueden optimizar
>>> implementandolos en el propio
>>> lenguaje.
>>
>> A ver si tengo claro el tema: lo que propones es que se pueda
>> acceder a "chunks" de memoria con los que operar con una aritmética
>> similar a la de los punteros de C ;-)
>
> No. Eso quedaría totalmente oculto y pertenece a la implementación del
> interprete y la forma en la que se generaría el código.
A propósito de array.
para los que no lo conocen:
>>> import array
>>> mi_array_de_double = array.array('d', [1.0,2.0,3.0,4.0,5.0])
>>> mi_array_de_double
array('d', [1.0, 2.0, 3.0, 4.0, 5.0])
>>> valor_a = mi_array_de_double[4] # (1)
>>> valor_b = 3.3
>>> mi_array_de_double[3] = valor_b # (2)
Si miras la implementación C del modulo de array
(Modules/_arraymodule.c), verás que el manejo "interno" de cada elemento
es muy eficiente.
Al extraer un elemento de un array (1) y al guardarlo (2) se invocan
a d_getitem y d_setitem respectivamente:
static PyObject *
d_getitem(arrayobject *ap, int i)
{
return PyFloat_FromDouble(((double *)ap->ob_item)[i]);
}
static int
d_setitem(arrayobject *ap, int i, PyObject *v)
{
double x;
if (!PyArg_Parse(v, "d;array item must be float", &x))
return -1;
if (i >= 0)
((double *)ap->ob_item)[i] = x;
return 0;
}
(para los neofitos, PyObject es la implementación en C de _cualquier_
objeto python. un puntero a PyObject es una referencia a un objeto de
python. esto es valido tanto dentro de los fuentes del python como
de las extensiones que los programadores quieran hacer al lenguaje.)
A pesar que ambas funciones son muy concisas, python no puede
igualar la velocidad de C en un bucle para un vector equivalente.
Aunque obviemos los chequeos de desborde (salteandonos ademas el
espiritu del lenguaje) otra vez el problema reside que el array recibe
y entrega los elementos como PyObject porque eso es lo que el
interprete maneja.
Se puede ver que en las dos funciones anteriores el coste mayor estará
en las llamadas a PyFloat_FromDouble(..) y en PyArg_Parse(..)
respectivamente.
En el estado actual del desarrollo del compilador y del interprete
no hay forma que al procesar el nombre 'valor_a' y 'valor_b' pueda
generar instrucciones que correspondan a un double nativo del
procesador y así poder evitar las conversiones de y hacia PyObject.
Chema en otro mensaje:
> Cuando se habla de interpretar, hay que recordar que la
> "interpretación" la realiza una máquina virtual (ya sea CPython,
> Stackless, JVM, Parrot, CLI,...), y que es a éste nivel donde se
> debería establecer la labor de optimización. Así mismo, hay que
> considerar que máquinas como JVM tienen cierta "aprensión" por todo
> lo que suene a punteros.
>
> Se puede afirmar que el lenguaje python en sí ya incluye la definición
> de arrays gracias al módulo 'array'. Ahora habría que ver se puede
> optimizar su uso con un módulo específico como se hace con el cPickle
> ó el cStringIO, con algún tipo de optimización de la máquina virtual
> como el psyco o compilando a C con el pyrex. Creo que es por ahí por
> donde hay que abordar el problema.
Asi es.
Desgraciadamente un JIT (o similar) para python está muy lejos de ser
una realidad cercana y no por falta de talento. Lo que invirtió Sun en
su Java HotSpot, Microsoft en su JIT para el CLI e incluso Icaza en
Mono (ahora de Novell) no creo que sea posible en nuestro querido
lenguaje. Ojalá me equivoque.
-H.
Más información sobre la lista de distribución Python-es