|
Autor |
SAS: "IF" vs. "ELSE IF" |
|
mrdjv2
Aktiv  Dabei seit: 05.07.2003 Mitteilungen: 1018
Wohnort: Aachen
 | Themenstart: 2018-01-26
|
Hallo,
mich würde mal interessieren, ob es für die performance in SAS wirklich einen Unterschied macht, ob ich mehrere if-Statements hintereinander habe, oder nach dem ersten if-Statement ein "else-if"-Statement kommt.
Ein Beispiel:
\sourceon SAS
if bedingung = 1 then ....
if bedingung = 2 then ...
if bedingung = 3 then ...
\sourceoff
oder eben
\sourceon SAS
if bedingung = 1 then ....
else if bedingung = 2 then ...
else if bedingung = 3 then ...
\sourceoff
Das Ergebnis ist bei beiden jedenfalls dasselbe. Einen Unterschied in der Performance konnte ich auch nicht feststellen.
Viele Grüße
Daniel
|
Profil
|
StrgAltEntf
Senior  Dabei seit: 19.01.2013 Mitteilungen: 8376
Wohnort: Milchstraße
 | Beitrag No.1, eingetragen 2018-01-26
|
Hallo mrdjv2,
das Ergebnis ist i. d. R. nicht dasselbe.
\sourceon
if x > 0 then x = x+1
if x > 1 then x = x+2
if x > 2 then x = x+3
\sourceoff
liefert andere Ergebnisse als
\sourceon
if x > 0 then x = x+1
else if x > 1 then x = x+2
else if x > 2 then x = x+3
\sourceoff
|
Profil
|
mrdjv2
Aktiv  Dabei seit: 05.07.2003 Mitteilungen: 1018
Wohnort: Aachen
 | Beitrag No.2, vom Themenstarter, eingetragen 2018-01-26
|
Ok, einverstanden ;-)
Das sehe ich ein!!
Aber angenommen, es ist dasselbe, was dann?
Das kann ja durchaus sein, wenn man aus einer Tabelle irgendwelche Schlüssel (z.B. Zahlen) in sprechende Texte übersetzen möchte.
Ich habe gehört (ohne eine Quelle dafür zu kennen), dass bei mehreren IF-statements immer die ganze Tabelle durchlaufen würde und bei if und dann else if würde sofort der nächste Datensatz abgearbeitet.
Da man aber nicht in einen Debugmodus wechseln kann, kann ich das auch nicht überprüfen.
Ebenfalls finde ich keine Quellen zu der Aussage von oben und wüsste einfach mal gerne, ob das wirklich so ist, oder ob das einfach nur Quatsch ist (was ich sogar glaube)
|
Profil
|
Buri
Senior  Dabei seit: 02.08.2003 Mitteilungen: 46882
Wohnort: Dresden
 | Beitrag No.3, eingetragen 2018-01-26
|
\quoteon(2018-01-26 15:01 - mrdjv2 in Beitrag No. 2)
... dass bei mehreren IF-statements immer die ganze Tabelle durchlaufen würde ...
\quoteoff
Hi mrdjv2,
bei mehreren if-Anweisungen ohne else wird jeder einzelne Test ausgewertet, das meinst du anscheinend mit "die ganze Tabelle".
Wenn else-Zweige vorkommen, dann bewirkt das, dass die restlichen Tests übergangen werden, wenn einer der Tests erfüllt war.
Da solch ein Test keine komplizierte Rechnung darstellt, ist der Unterschied in der Rechenzeit kaum feststellbar.
Allerdings machen es viele Programmierer so, dass sie an solchen Stellen aus Prinzip von Einsparmöglichkeiten Gebrauch machen, auch wenn der Effekt unbedeutend ist.
Wenn es sich um 10 oder mehr aufeinanderfolgende if-Anweisungen handelt, dann sollte man das auch tun, weil der Unterschied gegenüber den eigentlichen Rechenanweisungen bei einem sehr einfachen Anfängerprogramm dann schon etwas ausmacht.
Gruß Buri
|
Profil
|
StrgAltEntf
Senior  Dabei seit: 19.01.2013 Mitteilungen: 8376
Wohnort: Milchstraße
 | Beitrag No.4, eingetragen 2018-01-26
|
Es kommt auch darauf an, wie intelligent der Compiler ist. Eventuell merkt er, dass höchstens eine der if-Anweisungen zutreffen kann. Dann werden die restlichen if-Anweisungen vom resultierenden Maschinencode nicht mehr ausgewertet, sobald eine zutrifft.
Was der Compiler aus deinem Code macht, kannst du mit einem Debugger allerdings nicht feststellen. Im Debugger wird dein Code stur so ausgeführt, wie du ihn programmiert hast. Also werden dort immer alle if-Anweisungen ausgewertet, wenn du nicht mit else if programmierst.
Es kann sich übrigens durchaus in der Laufzeit bemerkbar machen, ob man ausschließlich mit if oder mit else if programmiert. Beispielsweise, wenn sich die if-Anweisungen innerhalb einer sehr langen for-Schleife befinden.
|
Profil
|
Buri
Senior  Dabei seit: 02.08.2003 Mitteilungen: 46882
Wohnort: Dresden
 | Beitrag No.5, eingetragen 2018-01-26
|
Hi mrdjv2,
um eine noch bessere Performance zu erreichen, sollte man anstelle von if-the-else-Anweisungen die für solche Fälle vorgesehene case-when-else-Anweisung benutzen. Man braucht dann die Variable bedingung nur einmal hinzuschreiben:
\sourceon SAS SQL
\numberson
case bedingung
when 1 then behandle den Fall bedingung = 1
when 2 then behandle den Fall bedingung = 2
... weitere Fälle
end
\sourceoff
Gruß Buri
|
Profil
|
mrdjv2
Aktiv  Dabei seit: 05.07.2003 Mitteilungen: 1018
Wohnort: Aachen
 | Beitrag No.6, vom Themenstarter, eingetragen 2018-01-29
|
Danke für eure Antworten.
@Buri: Nein, ich meinte tatsächlich "die ganze Tabelle". Wie gesagt - ich habe das so als Info erhalten und werde jedesmal fast schon blöd angemacht, wenn ich kein else benutze. Ich halte das aber für Quatsch und wollte mal wissen, wie es sich wirklich verhält.
|
Profil
|
AnnaKath
Senior  Dabei seit: 18.12.2006 Mitteilungen: 3818
Wohnort: hier und dort (s. Beruf)
 | Beitrag No.7, eingetragen 2018-03-17
|
Huhu zusammen,
manchmal geht "Probieren über Studieren":
\sourceon SAS
data sample ;
do id=1 to 100000 ;
class = floor(ranuni(-1)*10) ;
output ;
end ;
run ;
data performance1 ;
set sample ;
if(class eq 0) then result='a';
if(class eq 1) then result='b';
if(class eq 2) then result='c';
if(class eq 3) then result='d';
if(class eq 4) then result='e';
if(class eq 5) then result='f';
if(class eq 6) then result='g';
if(class eq 7) then result='h';
if(class eq 8) then result='i';
if(class eq 9) then result='j';
run ;
data performance2 ;
set sample ;
if(class eq 0) then result='a';
else if(class eq 1) then result='b';
else if(class eq 2) then result='c';
else if(class eq 3) then result='d';
else if(class eq 4) then result='e';
else if(class eq 5) then result='f';
else if(class eq 6) then result='g';
else if(class eq 7) then result='h';
else if(class eq 8) then result='i';
else if(class eq 9) then result='j';
run ;
proc sql ;
create table performance3 as
select id, class,
case
when class eq 0 then 'a'
when class eq 1 then 'b'
when class eq 2 then 'c'
when class eq 3 then 'd'
when class eq 4 then 'e'
when class eq 5 then 'f'
when class eq 6 then 'g'
when class eq 7 then 'h'
when class eq 8 then 'i'
when class eq 9 then 'j'
end as result
from sample ;
quit ;
\sourceoff
Wie nicht weiter überraschend, sind die ersten beiden Methoden in diesem kleinen Sample völlig gleichwertig. Spürbar schlechter schneidet dagegen die (naive) SQL-Abfrage ab:
\sourceon SAS (log)
NOTE: Die Datei WORK.PERFORMANCE1 weist 100000 Beobachtungen und 3 Variablen auf.
NOTE: Verwendet wurde: DATA-Anweisung - (Gesamtverarbeitungszeit):
Echtzeit 0.04 Sekunden
CPU-Zeit 0.04 Sekunden
NOTE: Die Datei WORK.PERFORMANCE2 weist 100000 Beobachtungen und 3 Variablen auf.
NOTE: Verwendet wurde: DATA-Anweisung - (Gesamtverarbeitungszeit):
Echtzeit 0.04 Sekunden
CPU-Zeit 0.04 Sekunden
NOTE: Tabelle WORK.PERFORMANCE3 wurde erstellt mit 100000 Zeilen und 3 Spalten.
NOTE: Verwendet wurde: PROZEDUR SQL - (Gesamtverarbeitungszeit):
Echtzeit 0.28 Sekunden
CPU-Zeit 0.07 Sekunden
\sourceoff
Bei einem etwas größeren Sample (10^7 Datensätze) kann man den zu erwartenden kleinen Performance-Unterschied zwischen den Varianten (1) und (2) dann bemerken:
\sourceon SAS (log)
NOTE: Die Datei WORK.PERFORMANCE1 weist 10000000 Beobachtungen und 3 Variablen auf.
NOTE: Verwendet wurde: DATA-Anweisung - (Gesamtverarbeitungszeit):
Echtzeit 4.75 Sekunden
CPU-Zeit 4.55 Sekunden
NOTE: Die Datei WORK.PERFORMANCE2 weist 10000000 Beobachtungen und 3 Variablen auf.
NOTE: Verwendet wurde: DATA-Anweisung - (Gesamtverarbeitungszeit):
Echtzeit 4.71 Sekunden
CPU-Zeit 4.38 Sekunden
NOTE: Tabelle WORK.PERFORMANCE3 wurde erstellt mit 10000000 Zeilen und 3 Spalten.
NOTE: Verwendet wurde: PROZEDUR SQL - (Gesamtverarbeitungszeit):
Echtzeit 5.24 Sekunden
CPU-Zeit 5.22 Sekunden
\sourceoff
Allerdings habe ich hier einfach auf meinem Laptop gerechnet. Bei einer ernsthaften Machine wird man auch bei noch größeren Samples keine nennenswerten Unterschiede feststellen.
lg, AK.
Trotzdem finde auch ich es unschön, unnötige Berechnungen durchführen zu lassen :-)
|
Profil
|
mrdjv2
Aktiv  Dabei seit: 05.07.2003 Mitteilungen: 1018
Wohnort: Aachen
 | Beitrag No.8, vom Themenstarter, eingetragen 2018-03-21
|
Danke für die Antworten!
Ich hätte selbst mal beim Log in die CPU-Zeit gucken können ;-)
Jetzt habe ich mal einen Test mit ca. 2 Mio Datensätzen und etwa 400 if-Abfragen gemacht.
Da habe ich mit "if else" etwa 0,7 sekunden und mit "if allein" etwa 2 Sekunden.
Schon spannend, dass das eine quasi dreimal so lange braucht...
|
Profil
|
mrdjv2 hat die Antworten auf ihre/seine Frage gesehen. mrdjv2 hat selbst das Ok-Häkchen gesetzt. |
|
All logos and trademarks in this site are property of their respective owner. The comments are property of their posters, all the rest © 2001-2023 by Matroids Matheplanet
This web site was originally made with PHP-Nuke, a former web portal system written in PHP that seems no longer to be maintained nor supported. PHP-Nuke is Free Software released under the GNU/GPL license.
Ich distanziere mich von rechtswidrigen oder anstößigen Inhalten, die sich trotz aufmerksamer Prüfung hinter hier verwendeten Links verbergen mögen. Lesen Sie die
Nutzungsbedingungen,
die Distanzierung,
die Datenschutzerklärung und das Impressum.
[Seitenanfang]
|