2013-06-20 15 views
5

Vorrei sapere come si può trattare il collo di bottiglia nel pezzo di codice indicato.Metodo efficiente per la ricerca di elementi nella matrice MATLAB

%% Points is an Nx3 matrix having the coordinates of N points where N ~ 10^6 
Z = points(:,3) 
listZ = (Z >= a & Z < b); % Bottleneck 
np = sum(listZ); % For later usage 
slice = points(listZ,:); 

Attualmente per N ~ 10^6, np ~ 1000 e number of calls to this part of code = 1000, la dichiarazione collo di bottiglia sta prendendo circa 10 secondi in totale, che è un grande pezzo di tempo rispetto al resto del mio codice.

Profiling Results

Alcuni ulteriori screenshot per un codice di esempio per solo la dichiarazione di indicizzazione come richiesto dal @EitanT

Profiling for sample code Profiling for sample code

+1

Sei sicuro che sia il collo di bottiglia (puoi mostrare i risultati del profilo)? E comunque qual'è 'num_calls'? –

+0

@EitanT Sì, ho controllato attraverso il profiler MATLAB stesso e questa affermazione è davvero il collo di bottiglia – OrangeRind

+0

@EitanT Ho aggiunto il risultato di profilazione – OrangeRind

risposta

8

Se l'uguaglianza da un lato non è importante che si può riformulare in un confronto unilaterale e diventa un ordine di grandezza più veloce:

Z = rand(1e6,3); 
a=0.5; b=0.6; 
c=(a+b)/2; 
d=abs(a-b)/2; 
tic 
for k=1:100, 
    listZ1 = (Z >= a & Z < b); % Bottleneck 
end 
toc 

tic 
for k=1:100, 
    listZ2 = (abs(Z-c)<d); 
end 
toc 

isequal(listZ1, listZ2) 

rendimenti

Elapsed time is 5.567460 seconds. 
Elapsed time is 0.625646 seconds. 

ans = 

    1 
+1

Ah! Questo mi ricorda [qualcosa che ho chiesto in passato] (http://stackoverflow.com/questions/12137233/matlab-performance-comparison-slower-than-arithmetic). In effetti, penso che questa sia la strada da percorrere. –

+0

Questo è buono! Anche se sto diventando un po 'meno di un ordine di grandezza nel programma reale forse a causa della complessità del resto del codice - ma penso ancora che si possa fare qualcosa di più. – OrangeRind

+2

Vedere anche la risposta accettata a [questa domanda di programmazione C recente] (http://stackoverflow.com/a/17095534/1165522). – horchler

1

provare a fare qualcosa di simile:

for i = 1:1000 
    x = (a >= 0.5); 
    x = (x < 0.6); 
end 

Ho trovato che fosse più veloce di:

for i = 1:1000 
    x = (a >= 0.5 & a < 0.6); 
end 

da circa 4 secondi:

Elapsed time is 0.985001 seconds. (first one) 
Elapsed time is 4.888243 seconds. (second one) 

Penso che il motivo per il rallentamento è l'elemento saggio & operazione.

+0

Si prega di leggere la domanda con più attenzione. :) – OrangeRind

+0

Ya capisco cosa intendi ora. – KronoS

+0

@OrangeRind vedere la risposta aggiornata. – KronoS

3

Supponendo che il caso peggiore:

  • elemento-saggio & non è in corto circuito internamente
  • i confronti sono single-threaded

Si sta facendo 2*1e6*1e3 = 2e9 confronti in ~ 10 secondi . Si tratta di ~ 200 milioni di confronti al secondo (~ 200 MFLOPS).

Considerando che è possibile fare un po 'di 1.7 GFLops on a single core, questo sembra piuttosto basso.

Stai utilizzando Windows 7? In tal caso, hai controllato le impostazioni di alimentazione? Sei su un processore mobile, quindi mi aspetto che per impostazione predefinita, ci sarà uno schema di consumo a basso consumo. Ciò consente alle finestre di ridimensionare la velocità di elaborazione, quindi ... verificarlo.

A parte questo .... non ne ho idea.

+0

Bel punto da notare lì - ma mi sono assicurato del piano di potenza - e durante il calcolo anche il boost di turbo è in corso dato che è in esecuzione a thread singolo. Controllerò il throughput della mia CPU attraverso geekbench e ti farò sapere comunque. – OrangeRind

Problemi correlati