LesezeichenAbonnierenRSS-Feed abonnieren
mfab
Quartz | Level 8

Hallo zusammen,

@FreelanceReinh: Vielen Dank für Deine Hinweise. Ojhe, ist das peinlich ... da habe ich wohl den Wald vor lauter Bäumen nicht gesehen und war mehr auf den Algorhythmus konzentriert, als auf SAS. Eine Typkonvertierung hatte ich ja auch im Kommentar und wollte von String mit INT() auf numerisch konvertieren statt mit INPUT ... eieiei.

Anbei (der Vollständigkeit halber) mein korrigierter Code. Ich habe nur die Notes im Log bereinigt, wobei ich wirklich erstaunt bin wie viel schneller eine alternative Verarbeitung ohne Strings laufen kann.
Zusätzlich habe ich mir erlaubt die gesuchte Nummer maximal 15 Stellen lang werden zu lassen statt 20. Wenn man die Lösung kennt, kann man natürlich auf 11 einschränken und mehr Performance gewinnen.

 

DATA _null_;
  length findme $15.;
  start_number = 18990000000;
  end_number = 99999999999;

  DO n = start_number TO end_number;
    findme = PUT(n,15.-l);
	digits = length(findme);
	quersumme = 0;
	/*rc=dosubl(cats('SYSECHO "n=',n,'"'));*/
    
	     /* Quersumme berechnen */
         DO i = 1 TO digits;
           quersumme = quersumme + INPUT(substr(findme,i,1),1.);
         END;

		 /* Test: durch 10 teilbar? */
         IF MOD(quersumme,10) EQ 0 THEN DO;
		     findlag = lag(findme);

		   /* Quersumme der vorherigen Zahl auch durch 10 teilbar? */
		   IF SUM(INPUT(findlag,15.),1) EQ INPUT(findme,15.) THEN DO;
               PUT "Ergebnis: " findlag " und " findme;
               STOP;
           END;
		 END;
  END;
RUN;



Was mich ja wundert ist die Tatsache, dass die automatische Konvertierung von SAS tatsächlich performanter läuft, als wenn man das selbst angibt. Ich komme auf Laufzeiten, die sich um 10-25% unterscheiden.

Den Hinweis mit "dosubl" für die Ausgabe im eGuide finde ich klasse, das sorgt in meinem Data-Step jedoch für mehr als doppelt so lange Laufzeiten.


(FULL)STIMER liefert meist gute Werte. Mir fehlt jedoch eine Option, unterschiedliche Lösungen im Detail zu testen.
Beispiel: Deklaration der zu durchlaufenden Zahlen einmal im DATA-Step vor der DO-Schleife und einmal die direkte Angabe in der DO-Schleife.

[...]
  start_number = 18990000000;
  end_number = 99999999999;

  DO n = start_number TO end_number;
[...]

vs

[...]
  DO n = 18990000000 TO 99999999999;
[...]

Oder per Macro-Variable, wie man es natürlich auch machen kann.
Hier liegen die Zeitunterschiede vermutlich in einem sehr kleinen Bereich, wodurch das schlecht im Log nachvollziehbar ist. Da können wahrscheinlich parallel laufende Zugriffe im System mehr Einfluss auf das Log haben. Dennoch würde mich interessieren, ob es Unterschiede gibt oder nicht.
Reine Neugier 🙂

@AndreasMenrath: Führt SAS das Length-Statement wirklich 10 mal aus, wenn es im Schleifen-Kopf steht? Damit hätte ich nicht gerechnet. Ich habe es jetzt im Code voran gestellt, konnte jedoch keine wesentlichen Unterschiede in der Laufzeit feststellen. (Auch wieder so ein Thema, das ich gerne genauer prüfen würde)

 

Beste Grüße in die Runde

Michael

FreelanceReinh
Jade | Level 19

Gern würde ich einmal "hinter die Kulissen" eines Datasteps schauen können ...  -- In dem Beispiel der Start- und Endwerte einer DO-Schleife gehe ich davon aus, dass es so gut wie keinen Unterschied macht, ob man sie explizit oder in (Datastep-)Variablen übergibt, denn die Übergabe erfolgt ja nur ein einziges Mal. Für diese Vermutung spricht jedenfalls, dass die Schleife nicht häufiger durchlaufen wird, wenn man den Endwert nachträglich erhöht:

data test;
a=10;
do i=1 to a;
  a=20;
  output;
end;
run; /* 10 obs. */

Insofern dürften auch Funktionsauswertungen in der Schleifendeklaration keinen nennenswerten Performance-Verlust für die betreffende Schleife bewirken.

 

Makrovariablen würden ohnehin aufgelöst, noch bevor der Datastep-Compiler überhaupt seine Arbeit aufnimmt.

 

Die (END_NUMBER - START_NUMBER + 1)-malige Auswertung der LENGTH-Funktion in der äußeren DO-Schleife wird dagegen selbstverständlich ihren Anteil zur Laufzeit beitragen. In der Tat wäre es nützlich, diesen Anteil einschätzen zu können.

AndreasMenrath
Pyrite | Level 9

Also das Thema Performanceoptimierung von SAS Programmen ist erfahrungsgemäß eine Geheimwissenschaft für sich.

Aus Neugier habe ich das ganze auch einmal mit "richtigen" Datentypen in einem DS2 Programm ausprobiert. Ich hätte erwartet, dass es dadurch etwas schneller wird, aber genau das Gegenteil war der Fall.

 

Zur Vollständigkeit hier noch der DS2 Code:

 

 

/* Parameters for program */
%let start_number = 18900000000; /* %let start_number = 1; */
%let end_number   = 19100000000; /* %let end_number = 2e10; */
%let divisor = 10;

proc ds2;

	data matches(overwrite=yes);
		dcl bigint number;
		dcl bigint current_number;
		dcl bigint previous_number;
		dcl int sum_of_digits;
		dcl int quersumme;

		method getQuerSumme(bigint zahl) returns int;
			sum_of_digits = 0;

			do while(zahl ne 0);
				sum_of_digits = sum_of_digits + mod(zahl, 10);
				zahl = zahl / 10;
			end;

			return(sum_of_digits);
		end;

		method init();

			do number = &start_number. to &end_number.;
				quersumme = getQuerSumme(number);

				if (mod(quersumme,&divisor.) eq 0) then
					do;
						current_number = number;

						if ( (current_number - previous_number) eq 1) then
							do;
								put 'NOTE: Zahlenpaar gefunden:';
								put 'NOTE- Zahl:' previous_number;
								put 'NOTE- Nachfolger:' current_number;
								output;
								stop;
							end;

						previous_number = number;
					end;
			end;
		end;

	enddata;
run;

quit;

 

PS: SAS als Skriptsprache ist selbst im Vergleich zu Managed Code wie Java oder .Net ziemlich langsam. Der gleiche Algorithmus in C# ist ungefähr um den Faktor 100 schneller.

Es sollte also noch etwas Potenzial zur Performanceverbesserung da sein Smiley (fröhlich)

Andreas
Fluorite | Level 6

Hallo Andreas,

gibt es denn irgendwann einmal vergleichende Messungen für die verschiedenen Lösungen?

Viele Grüße

Andreas

AndreasMenrath
Pyrite | Level 9
@Andreas: die Ergebnisse würden mich auch interessieren. Wenn sich ein neutraler Schiedsrichter finden lässt, sollte das auch kein Problem sein.
Ich nehme mich mal aus, da ich selbst zwei Implementierungen gepostet habe.

Hat jemand Lust die Beispiele zu vergleichen?

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

Register now!

Diskussionsstatistiken
  • 19 Antworten
  • 3572 Aufrufe
  • 5 Kudos
  • 7 in Unterhaltung