Základy programování v Matlabu - část 5
Ing. Petr Pokorný, Ph.D.
Vektorizace
Vektorizace je jeden z nejsilnějších nástrojů Matlabu pro optimalizaci výpočtů na velkých souborech dat.
Řada operací prováděných iterativně (pomocí cyklů apod.) lze řešit vektorizací a s využitím integrovaných funkcí Matlabu.
Využíváme zpravidla indexování pomocí vektorů, které nahradí výběr pomocí cyklu.
Pro hromadnou aplikaci operátoru na vybrané prvky používáme často tečkovaný operátor.
Výběr prvků vektorem hodnot
Jak bylo zmíněno v kapitole indexování, je vhodné uvažovat o zápisu prvků, které chceme indexovat, jako o vektoru. Předem definovaný vektor samotný lze pro indexování použít.
Výběr prvků vektorem logických hodnot
Jako vektor indexů je v řadě případů možné použít výstup logického dotazu.
R = [ 1 3 4 2 5 9 7 1 2 8 ]; % vektor vzdáleností
pozice_splneni_dotazu = find( bool_dotaz ) % find = vrátí indexy, na kterých je nenulová hodnota
R_vyber_1 = R( bool_dotaz )
R_vyber_2 = R( pozice_splneni_dotazu )
Příklady vektorizace
Příklad vektorizace součtu každého lichého prvku matice
S1 = S1 + A(in); % scitani
S2 = sum( A(1:2:end) ); % soucet na vybrane prvky
disp( [ 'Soucet S1 = ', num2str( S1 ), ', S2 = ', num2str( S2 ) ] );
Soucet S1 = 25017.2904, S2 = 25017.2904
disp( [ 'Cas t1 = ', num2str( t1 ), ' s, t2 = ', num2str( t2 ) ' s' ] );
Cas t1 = 0.2067 s, t2 = 0.0074789 s
Příklad součtu čtverců vybraných prvků matice
for in = 1:2:size(A,1) % cyklus pres radky
for jn = 1:2:size(A,2) % cyklus pres sloupce
S2 = sum( sum( A( 1:2:end,1:2:end ).^2 ) ); % mocneni teckovanym operatorem a soucet funkcemi
disp( [ 'Soucet ctvercu S1 = ', num2str( S1 ), ', S2 = ', num2str( S2 ) ] );
Soucet ctvercu S1 = 3333.5438, S2 = 3333.5438
disp( [ 'Cas t1 = ', num2str( t1 ), ' s, t2 = ', num2str( t2 ) ' s' ] );
Cas t1 = 0.061922 s, t2 = 0.0080619 s
Nejkratší vzdálenost města od bodu
X = [1034250 1034157 1034874];
Y = [ 733245 733105 733990];
X0 = 1034200; Y0 = 733100;
R(n) = sqrt( (X0 - X(n))^2 + (Y0 - Y(n))^2 );
Rmin2 = min( sqrt( (X0 - X).^2 + (Y0 - Y).^2 ) );
disp( [ 'R1 = ', num2str( Rmin ), ', R2 = ', num2str( Rmin2 ) ] )
R1 = 43.2897, R2 = 43.2897
disp( [ 'Cas t1 = ', num2str( t1 ), ' s, t2 = ', num2str( t2 ) ' s' ] );
Cas t1 = 0.015945 s, t2 = 0.0072317 s
Příklady k procvičení
Příklad 1
Přepište následující kód (nahraďte for cyklus) pro výpočet proměnné I pomocí vektorizace a porovnejte dobu výpočtu s dobou
. x = linspace( 0, 1, 50 ); y = cos( x );
I = ( x(end)-x(1) )/( length(x)-1 )*( ( y(1) + y(end) )/2 + s );
Příklad 2
Pomocí vektorizace optimalizujte následující kód redukce rozměru obrazu na polovinu a porovnejte dobu výpočtu s dobou
. I = imread( 'ngc6543a.jpg' ); % nacte obrazek NGC 6543 (z Matlab toolboxu)
% zmena rozliseni na polovinu
Ir = uint8( zeros( size(I) ) );
for iR = 1:2:size( I, 1 )
for iC = 1:2:size( I, 2 )
Ir( iRr, iCr, : ) = I( iR, iC, : );
Ir( iRr+1:end, :, : ) = []; Ir( :, iCr:end, : ) = [];