Table of Contents

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.
clear variables;
A = rand( 1, 10 );
indexy = [ 1 5 10 ];
A( indexy )
ans = 1×3
0.4111 0.8052 0.6422

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.
clear variables;
R = [ 1 3 4 2 5 9 7 1 2 8 ]; % vektor vzdáleností
bool_dotaz = R >= 3;
pozice_splneni_dotazu = find( bool_dotaz ) % find = vrátí indexy, na kterých je nenulová hodnota
pozice_splneni_dotazu = 1×6
2 3 5 6 7 10
R_vyber_1 = R( bool_dotaz )
R_vyber_1 = 1×6
3 4 5 9 7 8
R_vyber_2 = R( pozice_splneni_dotazu )
R_vyber_2 = 1×6
3 4 5 9 7 8

Příklady vektorizace

Příklad vektorizace součtu každého lichého prvku matice

clear variables;
A = rand( 100000, 1 );
% Pomoci for cyklu
t1 = tic; % mereni casu
S1 = 0;
for in = 1:2:length(A)
S1 = S1 + A(in); % scitani
end
t1 = toc( t1 );
% Vektorizaci
t2 = tic;
S2 = sum( A(1:2:end) ); % soucet na vybrane prvky
t2 = toc( t2 );
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

clear variables;
A = rand( 200, 200 );
% Pomoci for cyklu
t1 = tic; % mereni casu
S1 = 0;
for in = 1:2:size(A,1) % cyklus pres radky
for jn = 1:2:size(A,2) % cyklus pres sloupce
S1 = S1 + A(in,jn)^2;
end
end
t1 = toc( t1 );
% Vektorizaci
t2 = tic;
S2 = sum( sum( A( 1:2:end,1:2:end ).^2 ) ); % mocneni teckovanym operatorem a soucet funkcemi
t2 = toc( t2 );
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

clear variables;
X = [1034250 1034157 1034874];
Y = [ 733245 733105 733990];
X0 = 1034200; Y0 = 733100;
% For cyklem
t1 = tic;
R = zeros( size(X) );
for n = 1:length(X)
R(n) = sqrt( (X0 - X(n))^2 + (Y0 - Y(n))^2 );
end
Rmin = min(R);
t1 = toc( t1 );
% Vektorizaci
t2 = tic;
Rmin2 = min( sqrt( (X0 - X).^2 + (Y0 - Y).^2 ) );
t2 = toc( t2 );
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 .
clear variables;
x = linspace( 0, 1, 50 ); y = cos( x );
t1 = tic;
s = 0;
for iC = 2:length(y)-1
s = s + y(iC);
end
I = ( x(end)-x(1) )/( length(x)-1 )*( ( y(1) + y(end) )/2 + s );
t1 = toc(t1);

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 .
clear variables
I = imread( 'ngc6543a.jpg' ); % nacte obrazek NGC 6543 (z Matlab toolboxu)
figure
subplot(1,2,1)
image( I );
% zmena rozliseni na polovinu
t1 = tic;
Ir = uint8( zeros( size(I) ) );
iRr = 0;
for iR = 1:2:size( I, 1 )
iRr = iRr + 1;
iCr = 0;
for iC = 1:2:size( I, 2 )
iCr = iCr + 1;
Ir( iRr, iCr, : ) = I( iR, iC, : );
end
end
Ir( iRr+1:end, :, : ) = []; Ir( :, iCr:end, : ) = [];
t1 = toc(t1);
subplot(1,2,2)
image(Ir)