2010-07-04 11 views
6

Sto pensando che ho bisogno di usare numpy o qualche altra libreria per riempire questi array abbastanza velocemente ma non ne so molto. In questo momento questa operazione richiede circa 1 secondo su un PC Intel quad-core, ma ho bisogno che sia il più veloce possibile. Qualsiasi aiuto è molto apprezzato. Grazie!Come posso velocizzare le generazioni di array in 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 

risposta

1

si sta generando un milione e mezzo di numeri interi e la creazione di oltre un milione di riferimenti, mentre siete a questo. Sarei solo felice che ci vuole solo 1 secondo.

Se si sta facendo molto questo, si dovrebbe pensare ai modi per memorizzare i risultati nella cache.

Inoltre, essere su un quad-core qualsiasi cosa non aiuta in un caso come questo, si sta eseguendo un'operazione seriale che può essere eseguita solo su un core alla volta (e anche se lo si è threadato, CPython può solo eseguendo un thread Python puro alla volta a causa del Global Interpreter Lock).

+5

Perché questo è contrassegnato come una soluzione? Non risponde affatto alla domanda, e nel migliore dei casi è fuorviante: la creazione di un milione di interi e di un milione di riferimenti non richiede nulla di simile a un secondo in Python (su un PC tipico). –

8

Il mio computer di otto anni (lento) è in grado di creare un elenco di elenchi delle stesse dimensioni della matrice in 127 millisecondi.

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 

Non so cosa sia il modulo cv e come crei le matrici. Ma forse questa è la causa del codice lento.

Numpy può essere più veloce. La creazione di una serie di (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 

è possibile confrontare i tempi per la creazione di matrici utilizzando moduli diversi per vedere se c'è un vantaggio a cambiare: timeit module

+0

Sebbene la risposta risolva il problema del tempo, non fa esattamente quello che fa il codice nella domanda originale. Quindi, il tuo paragone è parzialità. Inoltre, i due codici che hai postato fanno cose diverse, quindi il confronto è ingiusto. –

+0

Ovviamente il mio codice non è uguale a quello della domanda. E nemmeno io dico che l'OP dovrebbe usare il mio codice. Gli esempi che fornisco sono per mostrare come è possibile misurare diversi metodi per la creazione di oggetti di grandi dimensioni simili alla matrice. La mia frase finale dice all'OP di scandagliare i diversi metodi in modo che possa decidere se c'è un vantaggio nel cambiare: non dovrebbe apportare modifiche finché non avrà la prova che un altro metodo è più veloce o più efficiente. –

0

Se si sta creando la stessa matrice più e più volte, potrebbe essere più veloce inizializzarlo usando cv.SetData()

0

Bene, è possibile utilizzare atlanticamente xrange invece di intervallo. intervallo crea un intero elenco di tutti quei numeri. xrange li genera 1 per 1. Dato che li stai usando solo uno alla volta, non hai bisogno di un elenco di essi.

+0

Penso che il moderno interprete Python cambi automaticamente "per intervallo (...)" a "per xrange (...)" automaticamente. Quindi è l'ottimizzazione solo in teoria o alcuni interpreti semplici (meno intelligenti). –

+0

In Python 2.x (incluso il appena rilasciato 2.7), il built-in 'range' restituisce ancora una lista, quindi usare' xrange' è un'ottimizzazione. In Python 3, 'range' restituisce un oggetto' range', un oggetto iterabile simile a ciò che 'xrange' restituisce in Python 2. –

+0

Le mie temporizzazioni in Python 2.6.1 mostrano range prendendo' 4.70' secondi e xrange prendendo '2.29'. Il codice che ho usato era 'per i in range (1000000): pass' e lo stesso per xrange. Timeit utilizzato con numero = 100. – Ponkadoodle

1

Il codice in Numpy che fa esattamente quello che hai fatto in OpenCV Python è

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

Se si sta utilizzando Python, considerare l'apprendimento delle diverse funzioni di NumPy vi aiuterà enormemente. Le funzioni OpenCV possono funzionare direttamente anche con gli array numpy. La sintassi di numpy in Python è molto meglio di OpenCV.

Ecco sono i tempi delle due versioni nel mio i7

time python test.py 

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

La mia versione:

time python test2.py 

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

non ho capito completamente quello che stavi cercando di raggiungere. Ma qui ci sono due esempi concreti e benchmark che potrebbero aiutarti. Entrambi fanno la stessa cosa, riempiono l'immagine 960x540 (matrice) con il rosso.

lento.py utilizza per cicli ad occupare matrice

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) 

Durata

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

fast.py utilizza NumPy ad occupare matrice

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) 

Durata

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

Utilizzando NumPy invece di cicli for è quasi 17x più veloce

Problemi correlati