wiki:ByteTwiddling

Byte Twiddling: Optimizando el manejo de (muuuuchos) bytes

La manera más obvia de manipular secuencias de bytes en Python casi nunca es la que procesa los datos de la forma más rápida. Para evitar caer en la pérdida de tiempo de programador que supone codificar un módulo en C, presentaremos en esta charla algunas de las técnicas que permiten operar de forma óptima sobre secuencias de bytes (que representan imágenes, sonidos y coordenadas), tanto de la biblioteca standard de Python como de algunas extensiones comunes como son NumPy, Imaging y PyOpenGL.

bytes, bytes, bytes

valores2 = []
for v in valores:
    valores2.append( operacion(v) )
# list comprehension
[ operacion(v) for v in valores ]

# retro
map(operacion, valores)

# generador
( operacion(v) for v in valores ) 

Uds dicen: "Ah, ya sé, Usaré C..." (o pyrex o alguna otra cosa) Yo digo: "Momento! Ya debe haber algo hecho!"

import moduloloco

moduloloco.operacionsobrebytes(bytes)

Caso 1: Optimizando tinysynth

  • alocado alocador
  • un juego en solamente 64kb de código
  • sin archivos de imágenes
  • sin archivos de sonidos

 http://python.org.ar/pyar/Proyectos/AlocadoAlocador

tinysynth

(gráfico)

  • generador de notas
  • secuenciador de partitura

tipos de datos: sample width y sample rate

 http://en.wikipedia.org/wiki/File:Signal_Sampling.png

  • sample rate (frecuencia)
  • sample width
  • número de canales (mono, stereo, 5.1)

Por ejemplo: 44.1 khz, 16bits, 2 canales

stdlib: wave

 http://docs.python.org/library/wave.html

stdlib: audioop

 http://docs.python.org/library/audioop.html

  • volmin, volmax = audioop.minmax(fragment, width)
  • potencia = audioop.rms(fragment, width)

PyGame: arrays

  • pygame.surfarray
  • pygame.sndarray
  • pygame.sndarray.make_sound

Un poco de teoría

tipos de datos

 http://en.wikipedia.org/wiki/Primitive_data_type

Enteros:

Tamaño Nombres Assembler y C Rango con signo Rango sin signo
8 bits Byte, char −128 a +127 0 a 255
16 bits Word, short int −32,768 a +32,767 0 a 65,535
32 bits Double Word, long int −2,147,483,648 a +2,147,483,647 0 a 4,294,967,295
64 bits Quad Word, long long −9,223,372,036,854,775,808 a +9,223,372,036,854,775,807 0 a 18,446,744,073,709,551,615

De punto flotante:

Tamaño Nombre en C Rango
32 bits float 3.4e-038..3.4e+038
64 bits double float 1.7e-308..1.7e+308

 http://en.wikipedia.org/wiki/Floating-point

endianness

 http://en.wikipedia.org/wiki/Endianness

  • little endian (intel, amd)

http://upload.wikimedia.org/wikipedia/commons/e/ed/Little-Endian.svg

  • big endian (motorola, powerpc, sparc)

http://upload.wikimedia.org/wikipedia/commons/5/54/Big-Endian.svg

stdlib: struct.Struct(format)

 http://docs.python.org/library/struct.html

De bytes a lista y vicerveza

  • hex editor -> mc
  • format: cbBhHiIllqQfdsp
  • <> little big endian
  • pack, unpack, format
    • struct.pack(fmt, v1, v2, ...)
    • lista = struct.unpack(fmt, string)
    • longitud = struct.calcsize(fmt)

struct format

Format C Type Python
x pad byte sin valor
c char string de largo uno
b signed char integer
B unsigned char integer
? _Bool bool
h short integer
H unsigned short integer
i int integer
I unsigned int integer o long
l long integer
L unsigned long long
q long long long
Q unsigned long long long
f float float
d double float
s char[] string
p char[] string
P void * long

Caso 2: Bustrofedón

Yaco hace la oveja eléctrica

oveja eléctrica es un proyecto en curso cuyo objetivo es crear un compositor artificial: un sistema que, mediante procesos existentes en una o más computadoras, sea capaz de crear música de manera intencional, no aleatoria e independiente de toda influencia humana. oveja eléctrica recibió el primer premio en la categoría proyecto multidisciplinario experimental (premio limb0 2003) del museo de arte moderno de buenos aires.

http://yaco.net/oe/mat/screenshot.jpg  http://blog.yaco.net/oveja-electrica/

(más imágenes en  http://yaco.net/oe/colabs-es.php )

Pregunta a la lista: Bustrofedón http://upload.wikimedia.org/wikipedia/commons/b/bf/Gortys_law_inscription.jpg generar un sonido extraño en base a una imagen

Sin optimizar:  http://proposicion.org.ar/lurker/message/20060630.025730.511174d6.es.html

  1. lee los pixels una imagen RGB, transformándolos en valores de gris de 16 bits
  2. los reordena en bustrofedón espejado
  3. los escribe como frames mono en un archivo de audio de sample rate rarito.

stdlib: array

 http://docs.python.org/library/array.html

  • (+) es parte de stdlib
  • (+) eficiente en espacio usado
  • (-) no hay operaciones eficientes

numpy

 http://numpy.scipy.org/

  • (-) módulo aparte: apt-get install python-numpy
  • (+) eficiente en espacio
  • (+) Muuuuchas operaciones

Python Imaging Library

  • módulo aparte: apt-get install python-imaging
  • raster images (rectángulos de pixels)

tipos de datos: Bits per pixel

 http://www.pythonware.com/library/pil/handbook/concepts.htm

  • 1 (1-bit pixels, black and white, stored with one pixel per byte)
  • L (8-bit pixels, black and white)
  • P (8-bit pixels, mapped to any other mode using a colour palette)
  • RGB (3x8-bit pixels, true colour)
  • RGBA (4x8-bit pixels, true colour with transparency mask)
  • I (32-bit signed integer pixels)
  • F (32-bit floating point pixels)

Bustrofedón optimizado

 http://proposicion.org.ar/lurker/message/20060630.191648.4f4294aa.es.html

Caso 3: Partículas con numpy

OpenGL

display lists

  • glNewList(id, GL_COMPILE)
  • glEndList()
  • glCallList(id)

vertex arrays

  • glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT)
  • glEnableClientState(GL_VERTEX_ARRAY)
  • glEnable(GL_TEXTURE_COORD_ARRAY)
  • glEnable(GL_COLOR_ARRAY)
  • glVertexPointer
  • glTexCoordPointer
  • glColorPointer
  • glDrawArrays
  • glPopClientAttrib()

tipos de datos

  • vertices: arrays de floats (x,y,z)
  • colores: arrays de floats (r,g,b,a)
  • coord. de texturas: arrays de floats (u, v)

http://www.gamedev.net/reference/programming/features/ogltm/texcoord.jpg

Conclusion

valores2 = []
for v in valores:
    valores2.append( operacion(v) )
import moduloloco

moduloloco.operacionsobrebytes(bytes)