MATLAB Language
Leistung und Benchmarking
Suche…
Bemerkungen
- Durch Profiling-Code wird die gefürchtete Praxis der " vorzeitigen Optimierung " vermieden , indem der Entwickler auf die Teile des Codes konzentriert wird, die Optimierungsmaßnahmen tatsächlich rechtfertigen.
- MATLAB-Dokumentationsartikel mit dem Titel " Messen der Leistung Ihres Programms ".
Leistungsengpässe mit dem Profiler erkennen
Der MATLAB Profiler ist ein Werkzeug zum Software-Profiling von MATLAB-Code. Mit dem Profiler ist es möglich, eine visuelle Darstellung der Ausführungszeit und des Speicherverbrauchs zu erhalten.
Der Profiler kann auf zwei Arten ausgeführt werden:
Klicken Sie auf die Schaltfläche "Run and Time" in der MATLAB-
.m
während einige.m
Dateien im Editor geöffnet sind (hinzugefügt in R2012b ).Programmgesteuert mit:
profile on <some code we want to test> profile off
Nachfolgend finden Sie einige Beispielcodes und das Ergebnis der Profilerstellung:
function docTest
for ind1 = 1:100
[~] = var(...
sum(...
randn(1000)));
end
spy
Aus den obigen Ausführungen erfahren wir, dass die spy
Funktion ungefähr 25% der gesamten Ausführungszeit benötigt. Im Fall von "realem Code" wäre eine Funktion, die einen so hohen Prozentsatz der Ausführungszeit cla
, ein guter Kandidat für die Optimierung, im Gegensatz zu Funktionen, die analog zu var
und cla
deren Optimierung vermieden werden sollte.
Darüber hinaus können Sie auf Einträge in der Spalte Funktionsname klicken, um eine detaillierte Aufgliederung der Ausführungszeit für diesen Eintrag anzuzeigen. Hier ist das Beispiel des Klickens spy
:
Es ist auch möglich, den Speicherverbrauch durch Ausführen des profile('-memory')
vor dem Ausführen des Profilers zu profilieren.
Vergleichen der Ausführungszeit mehrerer Funktionen
Die weit verbreitete Kombination aus tic
und toc
kann eine grobe Vorstellung von der Ausführungszeit einer Funktion oder von Codeausschnitten geben.
Für den Vergleich mehrerer Funktionen sollte es nicht verwendet werden. Warum? Es ist fast unmöglich, für alle Codeausschnitte gleiche Bedingungen bereitzustellen, um sie innerhalb eines Skripts mit der obigen Lösung zu vergleichen. Möglicherweise teilen die Funktionen den gleichen Funktionsraum und die gleichen gemeinsamen Variablen, so dass später genannte Funktionen und Codeausschnitte bereits zuvor initialisierte Variablen und Funktionen nutzen. Außerdem gibt es keine Einsicht, ob der JIT-Compiler diese nachfolgend genannten Snippets gleich behandeln würde.
Die dedizierte Funktion für Benchmarks ist timeit
. Das folgende Beispiel veranschaulicht seine Verwendung.
Es gibt das Array A
und die Matrix B
Es sollte bestimmt werden, welche Zeile von B
A
am ähnlichsten ist, indem die Anzahl der verschiedenen Elemente gezählt wird.
function t = bench()
A = [0 1 1 1 0 0];
B = perms(A);
% functions to compare
fcns = {
@() compare1(A,B);
@() compare2(A,B);
@() compare3(A,B);
@() compare4(A,B);
};
% timeit
t = cellfun(@timeit, fcns);
end
function Z = compare1(A,B)
Z = sum( bsxfun(@eq, A,B) , 2);
end
function Z = compare2(A,B)
Z = sum(bsxfun(@xor, A, B),2);
end
function Z = compare3(A,B)
A = logical(A);
Z = sum(B(:,~A),2) + sum(~B(:,A),2);
end
function Z = compare4(A,B)
Z = pdist2( A, B, 'hamming', 'Smallest', 1 );
end
Diese Art von Benchmark wurde erstmals in dieser Antwort gesehen .
Es ist in Ordnung "Single" zu sein!
Überblick:
Der Standarddatentyp für numerische Arrays in MATLAB ist double
. double
ist eine Gleitkommendarstellung von Zahlen , und dieses Format benötigt 8 Bytes (oder 64 Bits) pro Wert. In einigen Fällen, in denen z. B. nur mit Ganzzahlen gearbeitet wird oder wenn numerische Instabilität kein unmittelbar bevorstehendes Problem ist, ist eine solche hohe Bittiefe möglicherweise nicht erforderlich. Aus diesem Grund wird empfohlen, die Vorteile der single
(oder anderer geeigneter Typen ) zu berücksichtigen:
- Schnellere Ausführungszeit (besonders auf GPUs erkennbar).
- Die Hälfte des Speicherverbrauchs: kann erfolgreich sein, wenn
double
aufgrund eines Speichermangels ausfällt. kompakter beim Speichern als Dateien.
Das Konvertieren einer Variablen von einem beliebigen unterstützten Datentyp in einen single
erfolgt mithilfe von:
sing_var = single(var);
Einige häufig verwendete Funktionen (z. B. zeros
, eye
, ones
usw. ), die standardmäßig double
Werte ausgeben, ermöglichen die Angabe des Typs / der Klasse der Ausgabe.
Konvertieren von Variablen in einem Skript in eine nicht standardmäßige Genauigkeit / Typ / Klasse:
Seit Juli 2016 gibt es keine dokumentierte Möglichkeit, den Standard- MATLAB-Datentyp von double
zu ändern.
In MATLAB ahmen neue Variablen normalerweise die Datentypen von Variablen nach, die beim Erstellen verwendet wurden. Um dies zu veranschaulichen, betrachten Sie das folgende Beispiel:
A = magic(3);
B = diag(A);
C = 20*B;
>> whos C
Name Size Bytes Class Attributes
C 3x1 24 double
A = single(magic(3)); % A is converted to "single"
B = diag(A);
C = B*double(20); % The stricter type, which in this case is "single", prevails
D = single(size(C)); % It is generally advised to cast to the desired type explicitly.
>> whos C
Name Size Bytes Class Attributes
C 3x1 12 single
Daher scheint es ausreichend zu sein, mehrere Ausgangsvariablen umzuwandeln / umzuwandeln, damit die Änderung den gesamten Code durchläuft . Dies wird jedoch abgelehnt (siehe unten, Vorbehalte und Gefahren ).
Vorbehalte & Fallstricke:
Wiederholte Konvertierungen werden aufgrund der Einführung von numerischem Rauschen (beim Umwandeln von
single
zudouble
) oder Informationsverlust (beim Umwandeln vondouble
insingle
oder zwischen bestimmten Ganzzahltypen ) abgeraten , z.double(single(1.2)) == double(1.2) ans = 0
Dies kann etwas gemildert werden , indem
typecast
. Siehe auch Beachten Sie die Ungenauigkeit von Gleitkommazahlen .Ausschließlich auf die implizite Datentypisierung zu vertrauen (dh, was MATLAB für die Art der Ausgabe einer Berechnung hält) wird aufgrund verschiedener unerwünschter Auswirkungen abgeraten :
Informationsverlust : Wenn ein
double
erwartet wird, aber eine unvorsichtige Kombination vonsingle
unddouble
einesingle
Genauigkeit ergibt.Unerwartet hoher Speicherverbrauch : Wenn ein
single
Ergebnis erwartet wird, eine unvorsichtige Berechnung jedoch zu einerdouble
Ausgabe führt.Unnötiger Aufwand beim Arbeiten mit GPUs : Beim Mischen von
gpuArray
Typen (dh in VRAM gespeicherten Variablen) mit Nicht-gpuArray
Variablen (dh, die normalerweise im RAM gespeichert sind) müssen die Daten auf die eine oder andere Weise übertragen werden, bevor die Berechnung ausgeführt werden kann. Dieser Vorgang erfordert Zeit und kann bei wiederholten Berechnungen sehr auffällig sein.Fehler beim Mischen von Gleitkommatypen mit Ganzzahltypen : Funktionen wie
mtimes
(*
) sind nicht für gemischte Eingaben von Ganzzahl- und Gleitkommatypen definiert - und es wird ein Fehlermtimes
. Funktionen wietimes
(.*
) Sind für Integer-Eingaben überhaupt nicht definiert und werden erneut fehlerhaft.>> ones(3,3,'int32')*ones(3,3,'int32') Error using * MTIMES is not fully supported for integer classes. At least one input must be scalar. >> ones(3,3,'int32').*ones(3,3,'double') Error using .* Integers can only be combined with integers of the same class, or scalar doubles.
Zur besseren Lesbarkeit des Codes und zur Verringerung des Risikos unerwünschter Typen wird ein defensiver Ansatz empfohlen , bei dem Variablen explizit in den gewünschten Typ umgewandelt werden.
Siehe auch:
- MATLAB-Dokumentation: Gleitkommazahlen .
- Mathworks 'Technischer Artikel: Best Practices für die Konvertierung von MATLAB-Code in Fixed Point .
Neuanordnen eines ND-Arrays kann die Gesamtleistung verbessern
In einigen Fällen müssen wir Funktionen auf einen Satz von ND-Arrays anwenden. Schauen wir uns dieses einfache Beispiel an.
A(:,:,1) = [1 2; 4 5];
A(:,:,2) = [11 22; 44 55];
B(:,:,1) = [7 8; 1 2];
B(:,:,2) = [77 88; 11 22];
A =
ans(:,:,1) =
1 2
4 5
ans(:,:,2) =
11 22
44 55
>> B
B =
ans(:,:,1) =
7 8
1 2
ans(:,:,2) =
77 88
11 22
Beide Matrizen sind 3D. Nehmen wir an, wir müssen Folgendes berechnen:
result= zeros(2,2);
...
for k = 1:2
result(i,j) = result(i,j) + abs( A(i,j,k) - B(i,j,k) );
...
if k is very large, this for-loop can be a bottleneck since MATLAB order the data in a column major fashion. So a better way to compute "result" could be:
% trying to exploit the column major ordering
Aprime = reshape(permute(A,[3,1,2]), [2,4]);
Bprime = reshape(permute(B,[3,1,2]), [2,4]);
>> Aprime
Aprime =
1 4 2 5
11 44 22 55
>> Bprime
Bprime =
7 1 8 2
77 11 88 22
Jetzt ersetzen wir die obige Schleife für Folgendes:
result= zeros(2,2);
....
temp = abs(Aprime - Bprime);
for k = 1:2
result(i,j) = result(i,j) + temp(k, i+2*(j-1));
...
Wir haben die Daten neu angeordnet, um den Cache-Speicher nutzen zu können. Permutation und Umformung können kostspielig sein, aber wenn mit großen ND-Arrays gearbeitet wird, sind die mit diesen Vorgängen verbundenen Rechenkosten viel niedriger als mit nicht angeordneten Arrays.
Die Bedeutung der Vorbelegung
Arrays in MATLAB werden als fortlaufende Blöcke im Speicher gehalten, die von MATLAB automatisch zugewiesen und freigegeben werden. MATLAB verbirgt Speicherverwaltungsvorgänge wie die Größenänderung eines Arrays hinter einer einfach zu verwendenden Syntax:
a = 1:4
a =
1 2 3 4
a(5) = 10 % or alternatively a = [a, 10]
a =
1 2 3 4 10
Es ist wichtig zu verstehen, dass das Obige keine triviale Operation ist. a(5) = 10
bewirkt, dass MATLAB einen neuen Speicherblock der Größe 5 belegt, die ersten 4 Zahlen kopiert und den 5'ten Wert auf 10 setzt. Das ist eine O(numel(a))
und nicht O(1)
.
Folgendes berücksichtigen:
clear all
n=12345678;
a=0;
tic
for i = 2:n
a(i) = sqrt(a(i-1)) + i;
end
toc
Elapsed time is 3.004213 seconds.
a
wird in dieser Schleife n
mal neu zugewiesen (mit Ausnahme einiger von MATLAB durchgeführter Optimierungen)! Beachten Sie, dass MATLAB uns eine Warnung gibt:
"Die Variable 'a' scheint bei jeder Schleifeniteration die Größe zu ändern. Erwägen Sie eine Vorbelegung für die Geschwindigkeit."
Was passiert, wenn wir vorbelegen?
a=zeros(1,n);
tic
for i = 2:n
a(i) = sqrt(a(i-1)) + i;
end
toc
Elapsed time is 0.410531 seconds.
Wir können sehen, dass sich die Laufzeit um eine Größenordnung verringert.
Methoden für die Vorbelegung:
MATLAB bietet verschiedene Funktionen zur Zuordnung von Vektoren und Matrizen, abhängig von den spezifischen Anforderungen des Benutzers. Dazu gehören: zeros
, ones
, nan
, eye
, true
usw.
a = zeros(3) % Allocates a 3-by-3 matrix initialized to 0
a =
0 0 0
0 0 0
0 0 0
a = zeros(3, 2) % Allocates a 3-by-2 matrix initialized to 0
a =
0 0
0 0
0 0
a = ones(2, 3, 2) % Allocates a 3 dimensional array (2-by-3-by-2) initialized to 1
a(:,:,1) =
1 1 1
1 1 1
a(:,:,2) =
1 1 1
1 1 1
a = ones(1, 3) * 7 % Allocates a row vector of length 3 initialized to 7
a =
7 7 7
Ein Datentyp kann auch angegeben werden:
a = zeros(2, 1, 'uint8'); % allocates an array of type uint8
Es ist auch einfach, die Größe eines vorhandenen Arrays zu klonen:
a = ones(3, 4); % a is a 3-by-4 matrix of 1's
b = zeros(size(a)); % b is a 3-by-4 matrix of 0's
Und klonen Sie den Typ:
a = ones(3, 4, 'single'); % a is a 3-by-4 matrix of type single
b = zeros(2, 'like', a); % b is a 2-by-2 matrix of type single
Beachten Sie, dass „ Gefällt mir “ auch Komplexität und Sparsamkeit klont .
Die Vorabzuordnung wird implizit mithilfe einer Funktion erreicht, die ein Array mit der endgültigen erforderlichen Größe zurückgibt, z. B. rand
, gallery
, kron
, bsxfun
, colon
und viele andere. Eine übliche Methode zum Zuweisen von Vektoren mit linear variierenden Elementen ist beispielsweise die Verwendung des Doppelpunktoperators (entweder mit der 2- oder 3-Operandenvariante 1 ):
a = 1:3
a =
1 2 3
a = 2:-3:-4
a =
2 -1 -4
Zellen-Arrays können mit der Funktion cell()
auf die gleiche Weise wie zeros()
zugewiesen werden.
a = cell(2,3)
a =
[] [] []
[] [] []
Beachten Sie, dass Zellenarrays funktionieren, indem sie Zeiger auf die Speicherstellen des Zelleninhalts halten. Daher gelten alle Vorbelegungstipps auch für die einzelnen Zellenarrayelemente.
Lesen Sie weiter:
- Offizielle MATLAB-Dokumentation zum Thema " Vorbelegung des Speichers ".
- Offizielle MATLAB-Dokumentation zu " Wie MATLAB Speicher belegt ".
- Vorbelegungsperformance bei undokumentiertem Matlab .
- Grundlegendes zur Array-Vorbelegung von Loren in der Kunst von MATLAB