2010-07-04 11 views
6

Estoy pensando que necesito usar Numpy o alguna otra biblioteca para llenar estos arreglos lo suficientemente rápido pero no sé mucho al respecto. En este momento, esta operación lleva aproximadamente 1 segundo en una PC Intel de cuatro núcleos, pero necesito que sea lo más rápido posible. Cualquier ayuda es muy apreciada. ¡Gracias!¿Cómo puedo acelerar las generaciones de array en Python?

import cv 

class TestClass: 

    def __init__(self): 

    w = 960 
    h = 540 

    self.offx = cv.CreateMat(h, w, cv.CV_32FC1) 
    self.offy = cv.CreateMat(h, w, cv.CV_32FC1) 

    for y in range(h): 
     for x in range(w): 
     self.offx[y,x] = x 
     self.offy[y,x] = y 

Respuesta

1

Está generando medio millón de enteros y creando más de un millón de referencias mientras lo hace. Solo me alegra que solo tome 1 segundo.

Si está haciendo esto mucho, debería pensar en formas de almacenar en caché los resultados.

Además, estar en un quad-core algo no ayuda en un caso como este, estás realizando una operación en serie que solo puede ejecutarse en un núcleo a la vez (e incluso si lo enhebraste, CPython puede solo ejecutar un hilo de Python puro a la vez debido al bloqueo de Intérprete global).

+5

¿Por qué es esto marcó como una solución? No responde en absoluto a la pregunta, y en el mejor de los casos es engañosa: la creación de un millón de enteros y un millón de referencias no lleva cerca de un segundo en Python (en una PC típica). –

8

Mi computadora de ocho años (lenta) puede crear una lista de listas del mismo tamaño que su matriz en 127 milisegundos.

C:\Documents and Settings\gdk\Desktop>python -m timeit "[[x for x in range(960)] 
for y in range(540)]" 
10 loops, best of 3: 127 msec per loop 

No sé qué es el módulo cv y cómo crea las matrices. Pero tal vez esta es la causa del código lento.

Numpy puede ser más rápido. Creación de una matriz de (Python int) 1s:

C:\Documents and Settings\gdk\Desktop>python -m timeit -s "from numpy import one 
s" "ones((960, 540), int)" 
100 loops, best of 3: 6.54 msec per loop 

Es posible comparar los tiempos para crear matrices utilizando diferentes módulos para ver si hay un beneficio para el cambio: timeit module

+0

Aunque su respuesta aborda el problema del tiempo, no hace exactamente lo que hace el código en la pregunta original. Por lo tanto, tu comparación es parcial. Además, los dos códigos que publicó hacen cosas diferentes, por lo que la comparación es injusta. –

+0

Por supuesto, mi código no es el mismo que el de la pregunta. Y tampoco digo que el OP debería usar mi código. Los ejemplos que proporciono muestran cómo se pueden cronometrar diferentes métodos para crear objetos grandes similares a la matriz. Mi oración final le dice al OP que tome el tiempo de los diferentes métodos para que pueda decidir si hay un beneficio para el cambio; no debe hacer un cambio hasta que tenga evidencia de que otro método es más rápido o más eficiente. –

0

Si va a crear la misma matriz una y otra vez, puede ser más rápido inicializarlo usando cv.SetData()

0

Bueno, al menos puede usar xrange en lugar de rango. rango crea una lista completa de todos esos números. xrange los genera de 1 en 1. Como solo los está usando uno a la vez, no necesita una lista de ellos.

+0

Creo que el intérprete moderno de Python cambia "de rango (...)" a "para xrange (...)" automáticamente. Por lo tanto, solo se trata de optimización en teoría o de algunos intérpretes simples (menos inteligentes). –

+0

En Python 2.x (incluido el recién publicado 2.7), el 'rango' incorporado aún devuelve una lista, por lo que usar' xrange' es una optimización. En Python 3, 'range' devuelve un objeto' range', un objeto iterable similar al que devuelve 'xrange' en Python 2. –

+0

Mis tiempos en Python 2.6.1 muestran el rango tomando' 4.70' segundos y xrange tomando '2.29'. El código que utilicé fue 'for i in range (1000000): pass' y lo mismo para xrange. Timeit usado con número = 100. – Ponkadoodle

1

El código en Numpy que hace exactamente lo que hizo en OpenCV Python es

import numpy as np 
offsetx, offsety = np.meshgrid(range(960),range(540)) 

Si está utilizando Python, considere el aprendizaje de las diferentes funciones de numpy le ayudará enormemente. Las funciones de OpenCV también pueden trabajar directamente con matrices numpy. Sin embargo, la sintaxis de numpy en Python es mucho mejor que OpenCV.

Aquí es decir son los tiempos de las dos versiones en mi i7

time python test.py 

real 0m0.654s 
user 0m0.640s 
sys 0m0.010s 

Mi versión:

time python test2.py 

real 0m0.075s 
user 0m0.060s 
sys 0m0.020s 
0

no entendía completamente lo que estaba tratando de lograr. Pero aquí hay dos ejemplos concretos y puntos de referencia que pueden ayudarle. Ambos hacen lo mismo, llenan una imagen de 960x540 (matriz) con rojo.

lento.py utiliza para bucles para llenar gama

import cv2 
import numpy as np 

width, height = 960, 540 
image = np.zeros((height, width, 3), np.uint8) 
# Fill array with red 
for y in range(height): 
    for x in range(width): 
     image[y, x] = (0, 0, 255) 

cv2.imwrite('red.jpg', image) 

Duración

$ time python slow.py 
real 0m2.240s 
user 0m2.172s 
sys 0m0.040s 

fast.py utiliza para llenar numpy gama

import cv2 
import numpy as np 

width, height = 960, 540  
image = np.zeros((height, width, 3), np.uint8) 
# Fill array with red 
image[:] = (0, 0, 255) 
cv2.imwrite('red.jpg', image) 

Duración

$ time python fast.py 
real 0m0.134s 
user 0m0.084s 
sys 0m0.024s 

Usando numpy en lugar de los bucles es casi 17 veces más rápido

Cuestiones relacionadas