2012-05-10 28 views
5

código vectorizado en Matlab corre mucho más rápido que un bucle (ver Parallel computing in Octave on a single machine -- package and example para obtener resultados concretos en la octava)vectorización de meshgrid en Matlab (o de octava)

Dicho esto, hay una manera de vectorizar el código se muestra a continuación en Matlab u Octave?

x = -2:0.01:2; 
y = -2:0.01:2; 
[xx,yy] = meshgrid(x,y); 
z = sin(xx.^2-yy.^2); 
+0

Eche un vistazo a la implementación 'bsxfun', que también se refiere al uso de GPU [aquí] (http://stackoverflow.com/a/25162350/3293881) – Divakar

Respuesta

6

como ha señalado @Jonas, hay algunas opciones disponibles en MATLAB y que funciona mejor depende de algunos factores como:

  • ¿Qué tan grande es su problema
  • cuántas máquinas le disponer
  • ¿tiene una GPU
  • ¿se MATLAB ya multihilo las operaciones

Muchos EL Las operaciones de ementwise son multiproceso en MATLAB ahora, en cuyo caso, generalmente no tiene mucho sentido usar PARFOR (a menos que tenga varias máquinas y licencias de MATLAB Distributed Computing Server disponibles).

Los problemas realmente grandes que necesitan la memoria de varias máquinas se pueden beneficiar de distributed arrays.

El uso de la GPU puede superar el rendimiento multiproceso de una sola máquina si el problema es de un tamaño y tipo adecuados para el cálculo de la GPU. El código vectorizado tiende a ser el ajuste más natural para la paralelización a través de la GPU. Por ejemplo, podría escribir su código usando gpuArray s de Parallel Computing Toolbox como tal y hacer que todo se ejecute en la GPU.

x = parallel.gpu.GPUArray.colon(-2,0.01,2); 
y = x; 
[xx,yy] = meshgrid(x,y); % xx and yy are on the GPU 
z = arrayfun(@(u, v) sin(u.*u-v.*v), xx, yy); 

I convertidos la última línea no en una llamada arrayfun ya que es más eficiente cuando se utiliza gpuArray s.

+0

Gran! Tienes razón en que Matlab automáticamente multiplique el cálculo que di más arriba. Estaba ejecutando el cómputo desde mi casa sin la Parallel Computing Toolbox, y ahora lo ejecuté en una máquina con la caja de herramientas y lo hice en paralelo. Y gracias por el ejemplo GPU ... nunca han utilizado una GPU, pero sospecho que uno va a ser útil en el futuro, y es bueno saber el código parece sencillo – db1234

+0

embargo, su un antiguo puesto, pude para implementarlo con bsxfun en GPU y obtuve buenas aceleraciones. ¡Publicó una solución aquí en el mismo! – Divakar

5

En Matlab, la única manera de obtener las funciones integradas de vectorizadas a multihilo es esperar a que MathWorks a implement them como tales.

Alternativamente, puede escribir el cálculo vectorizado como un bucle, y ejecutarlos en paralelo usando parfor.

Finalmente, varias funciones son GPU-enabled, por lo que con acceso a la caja de herramientas de procesamiento en paralelo puede paralelizar estas operaciones, incluyendo la resta y la potencia de los elementos.

+0

' for' lazos en Matlab tienden a ser más lentos que vectorizados cálculos Entonces, la situación ideal para un rendimiento óptimo parece ser intentar y paralelizar el código vectorizado, si es posible. – db1234

+1

@dblazevski: 'parfor' ayuda, pero es posible que desee buscar la ejecución de algún código en la GPU. Ver mi edición Además, en versiones recientes de Matlab, los bucles 'for' se han vuelto sorprendentemente rápidos. – Jonas

+0

Es cierto. Probé el ejemplo dado en http://stackoverflow.com/questions/10520495/parallel-computing-in-octave-on-a-single-machine-package-and-example/10543033#10543033 I incluso refinado la rejilla una mucho. En Matlab, el bucle 'for' fue más lento, pero solo alrededor de 5 veces más que la versión vectorizada. En Octave, el código de bucle 'for' tomó * mucho * más tiempo (como más de 100 veces más ...). Tengo curiosidad por las GPU desde hace un tiempo, aunque no las he probado ... ¿Conoces un punto de partida para aprender a usar/programar una GPU? – db1234

5

vectorización de meshgrid y ndgrid

Si usted todavía está interesado en encontrar una aplicación vectorizado para hacer que el código basado en meshgrid el problema más rápido, permítame sugerirle un método vectorizado con bsxfun y es portado versión de la GPU. Creo firmemente que las personas deben considerar vectorization with GPUs como una opción prometedora para acelerar los códigos MATLAB. Los códigos que emplean meshgrid o ndgrid y cuyas salidas se deben operar con alguna operación de elemento configuran un terreno perfecto para emplear bsxfun en esos códigos. Para agregar a eso, el uso de GPU con bsxfun, que le permite trabajar en los elementos de forma independiente con cientos y miles de núcleos CUDA disponibles, lo hace perfecto para la implementación de GPU.

Para su problema específico, las entradas eran -

x = -2:0.01:2; 
y = -2:0.01:2; 

A continuación, tenías -

[xx,yy] = meshgrid(x,y); 
z = sin(xx.^2-yy.^2); 

Con bsxfun, esto se convierte en una sola línea -

z = sin(bsxfun(@minus,x.^2,y.^2.')); 

Benchmarking

GPU puntos de referencia se tomaron desde Measure and Improve GPU Performance.

%// Warm up GPU call with insignificant small scalar inputs 
temp1 = sin_sqdiff_vect2(0,0); 

N_arr = [50 100 200 500 1000 2000 3000]; %// array elements for N (datasize) 
timeall = zeros(3,numel(N_arr)); 

for k = 1:numel(N_arr) 
    N = N_arr(k); 
    x = linspace(-20,20,N); 
    y = linspace(-20,20,N); 

    f = @() sin_sqdiff_org(x,y);%// Original CPU code 
    timeall(1,k) = timeit(f); 
    clear f 

    f = @() sin_sqdiff_vect1(x,y);%// Vectorized CPU code 
    timeall(2,k) = timeit(f); 
    clear f 

    f = @() sin_sqdiff_vect2(x,y);%// Vectorized GPU(GTX 750Ti) code 
    timeall(3,k) = gputimeit(f); 
    clear f 
end 

%// Display benchmark results 
figure,hold on, grid on 
plot(N_arr,timeall(1,:),'-b.') 
plot(N_arr,timeall(2,:),'-ro') 
plot(N_arr,timeall(3,:),'-kx') 
legend('Original CPU','Vectorized CPU','Vectorized GPU (GTX 750 Ti)') 
xlabel('Datasize (N) ->'),ylabel('Time(sec) ->') 

funciones asociadas

%// Original code 
function z = sin_sqdiff_org(x,y) 
[xx,yy] = meshgrid(x,y); 
z = sin(xx.^2-yy.^2); 
return; 

%// Vectorized CPU code 
function z = sin_sqdiff_vect1(x,y) 
z = sin(bsxfun(@minus,x.^2,y.^2.')); %//' 
return; 

%// Vectorized GPU code 
function z = sin_sqdiff_vect2(x,y) 
gx = gpuArray(x); 
gy = gpuArray(y); 
gz = sin(bsxfun(@minus,gx.^2,gy.^2.')); %//' 
z = gather(gz); 
return; 

Resultados

enter image description here

Conclusiones

Como muestran los resultados, el método vectorizado con GPU muestra un buen rendimiento imp rovement que es aproximadamente 4.3x contra el código CPU vectorizado y 6x contra el código original. Tenga en cuenta que GPU tiene que superar una sobrecarga mínima que se requiere con su configuración, por lo que se necesita al menos una entrada de tamaño decente para ver la mejora. Con suerte, la gente exploraría más de vectorization with GPUs, ¡ya que no se podría enfatizar lo suficiente!