================================= 3. PowerBASIC und der CoProzessor ================================= 3.1. Untersttzt PowerBASIC einen CoProzessor? 3.2. Welche Flieákommabibliothek ist fr mich die optimale? 3.3. Macht sich der CoProzessor auch bei $FLOAT PROCEDURE bemerkbar? 3.4. Welche PowerBASIC-Funktionen sind betroffen? 3.5. m”gliche Ursachen fr den CoProzessor-Effekt 3.6. PowerBASIC-Benchmark Source 3.1. Untersttzt PowerBASIC einen CoProzessor? ---------------------------------------------- Die Antwort lautet ganz einfach JA. Bereits in den Compiler-Optionen haben Sie die M”glichkeit drei verschiedene Flieákommabibliotheken auszuw„hlen. Aber mit dieser Untersttzung des CoProzessors sind unter PowerBASIC einige Haken verbunden, die es hier aufzuzeigen geht damit sie schnellere und hoffentlich nur sauber funktionierende Programme entwickeln. 3.2. Welche Flieákommabibliothek ist fr mich die optimale? ----------------------------------------------------------- PowerBASIC bietet insgesamt drei Flieákommabibliotheken an: a) $FLOAT EMULATE Dieses ist die DEFAULT-Bibiothek und dadurch in der Regel bei ca 95% der Anwender im Einsatz. Sie zeichnet sich durch automatische Unter- sttzung des i87 aus, sofern ein solcher CoProzessor gefunden wurde. Der enorme Nachteil liegt aber sofort auf der Hand. PowerBASIC testet st„ndig auf einen CoProzessor und wird dadurch erheblich langsamer sofern wirklich kein i87 installiert ist. b) $FLOAT PROCEDURE Diese Bibliothek ist mit Abstand die schnellste, sofern kein Co- Prozessor installiert ist. c) $FLOAT NPX Mit Abstand liegt diese Bibliothek vorne, sofern jedenfalls ein i87 vorhanden ist. 3.3. Macht sich der Coprozessor auch bei $FLOAT PROCEDURE bemerkbar? -------------------------------------------------------------------- Auch hier ist die Antwort ganz klar: JA. Obwohl PowerBASIC keine Coprozessoruntersttzende Flieákommabibliothek eingebunden hat, l„át sich dies anhand der beiliegenden Source sehr deutlich beweisen. Des R„tsels Ursache liegt in der PowerBASIC-Runtime-Bibliothek, diese untersttzt schon von Hause aus einen i87. Deshalb lassen sich auch die Geschwindigkeitsauswirkungen der verschiedenen Flieákommabibliotheken nicht verallgemeinern. 3.4. Welche PowerBASIC-Funktionen sind betroffen? ------------------------------------------------- Als betroffende internen PowerBASIC-Funktionen w„re da vorallem SELECT CASE zu nennen. Messungen haben gezeigt das SELECT CASE mit i87 5 Sekunden braucht. Unter den gleichen Voraussetzungen (aber ohne i87) bis zu 200 Sekunden ben”tigen kann ($FLOAT EMULATE). Enorme Ver- besserungen waren bereit mit $FLOAT PROCEDURE zu erreichen (jetzt nur noch 35 Sekunden). Im allgemeinen kann gesagt werden: SELECT CASE hat nichts in zeit- kritischen Routinen zu suchen. Ebenso, aber bei weitem nicht so extrem, ist die PRINT-Ausgabe von nummerischen Ausdrcken betroffen. 3.5. m”gliche Ursachen fr den CoProzessor-Effekt ------------------------------------------------- Meines Erachtens hat dieser Effekt recht natrliche Ursachen, da alle betroffenden Befehle mit dem neuen 80-stelligen Zahlensystem umgehen k”nnen mssen. Anscheinend haben die Programmierer von PowerBASIC ver- sucht den zus„tzlichen Rechenaufwand durch Einsatz des CoProzessors wieder wettzumachen. Wobei Ihnen dies bei vorhandenem CoProzessor auch recht gut gelungen ist. Andererseits kann man sich fragen, warum der Compiler dies nicht besser optimiert sofern nur normale 16/32bit Zahlen eingesetzt werden. 3.6. PowerBASIC-Benchmark Source -------------------------------- Die hier beigefgte Source soll Ihnen die Zusammenh„nge der vorherigen Abschnitte besser demonstrieren. Am besten Sie compilieren die Source und testen einfach ein wenig herum. Source: REM ***************************************************************** REM REM PBBENCH.EXE - Performance-Meáprogramm fr PowerBASIC REM REM Zum Feststellen der Geschwindigkeitsunterschiede einzelner REM PowerBASIC-Befehle in Verbindung der verwendeten Flieákomma- REM bibiothek bei vorhanden bzw. nichtvorhandensein eines REM Coprozessors. REM REM Copyright: Thomas Gohel & Andras Hoeffken Version 2.10 REM Alle Rechte vorbehalten REM REM ----------------------------------------------------------------- REM REM Wichtige Hinweise: REM Fr halbwegs reale Meáungen muá sich der Prozessor im REAL- REM Mode befinden. Es drfen keine TSR-Treiber installiert sein, REM also kein KEYB.COM, SMARTDRV.EXE oder „hnliches. REM Wichtig: REM Fr eine halbwegs genaue Meáung muá das Programm mehrmals REM aufgerufen und dann Mittelwerte gebildet werden. REM REM Besitzer von 486'er/586'ern bzw. 286/386'ern mit REM installiertem x87'er Prozessor k”nnen den CoProzessor fr REM PowerBASIC mit dem in dieser Source beigefgtem Listing REM Ein/Aus schalten. Das muá allerdings die IDE bzw. das fertige REM EXE-File erneut gestartet werden! REM REM ************************************************************* REM $COMPILE EXE "PBBENCH.EXE" $CPU 80386 $LIB ALL OFF REM $FLOAT NPX ' fr Rechner mit CoProzeáor (am ' schnellsten) REM $FLOAT PROCEDURE ' fr Rechner ohne CoProzeáor (von mir ' empfohlen) REM $FLOAT EMULATE ' automatisch untersttzen (ohne ' Coprozessor extrem langsam!! REM $DEBUG MAP OFF PRINT PRINT "Performance-Messprogramm fuer PowerBASIC";: PRINT TAB(58); "(c) A.Hoeffken/Th.Gohel";: PRINT TAB(68); "Version 2.10";: PRINT STRING$(80,"-"); PRINT a% = 1 ' diverse Variablen i% = 1234 ' -"- e& = 12345678 ' -"- REM Zc1! fr 5000000-Schleifen ; zum Herausrechnen der Zeiten REM Zc2! fr 2000000-Schleifen ; fr die FOR/NEXT-Schleifen REM Zc3! fr 100000-Schleifen REM Zc4! fr 2000-Schleifen IF pbvnpx > 0 THEN PRINT "CoProzessor " + CHR$(pbvnpx+48) + "87 gefunden!" PRINT PRINT "Soll der CoProzessor fr die n„chste Messung "; PRINT "ausgeschaltet werden (J/N)?" BEEP A$ = UCASE$(INPUT$(1)) IF A$ = "J" THEN CoPro "AUS" ELSE PRINT "kein CoProzessor gefunden!" PRINT PRINT "Soll der CoProzessor fr die n„chste Messung "; PRINT "wieder eingeschaltet werden (J/N)?" PRINT PRINT "Hinweis: Einschalten dieses Testes bei nicht "; PRINT "installiertem Coprozessor fhrt" PRINT " zum Absturz!" BEEP A$ = UCASE$(INPUT$(1)) IF A$ = "J" THEN CoPro "EIN" END IF PRINT GOSUB HoleZeitKonstanten GOSUB MesseFORNEXT GOSUB MesseIFTHEN GOSUB MesseSELECTCASE GOSUB MesseMATHEMATIK GOSUB MesseSTRING GOSUB MesseNUMPRINT GOSUB MesseSTRPRINT PRINT END '******************************************************************** ' Holen der einzelen Zeitkonstanten fr die einzelnen Messungen '******************************************************************** HoleZeitKonstanten: PRINT "Messung der Zeitkonstanten "; t1! = TIMER FOR i& = 1 TO 2000 ' Zeit fr 2000-Schleifen ausmessen NEXT i& t2! = TIMER Zc4! = t2! - t1! PRINT "."; t1! = TIMER FOR i& = 1 TO 5000000 ' Zeit fr 5-Mio-Schleifen ausmessen NEXT i& t2! = TIMER Zc1! = t2! - t1! PRINT "."; t1! = TIMER FOR i& = 1 TO 100000 ' Zeit fr 100000-Schleifen ausmessen NEXT i& t2! = TIMER Zc3! = t2! - t1! PRINT "." t1! = TIMER FOR i& = 1 TO 2000000 ' Zeit fr 2-Mio-Schleifen ausmessen NEXT i& t2! = TIMER Zc2! = t2! - t1! RETURN '******************************************************************** ' ' Hier nun die einzelnen Routinen zur Zeitmessung der einzelnen ' Befehle. Im Prinzip ist die Messung immer abh„ngig vom verwendeten ' Computersystem und dem installiertem Betriebssytem. Gerade aber in ' Verbindung mit PowerBASIC, der verwendeten Flieákommabibiliothek ' und dem Vorhandensein eines CoProzessors lassen sich erhebliche ' Unterschiede bei der Performance einzelner Befehle ermitteln. ' '******************************************************************** MesseFORNEXT: PRINT "Messe FOR/NEXT : "; t1! = TIMER FOR i& = 1 TO 5000000 '5-Millionen-Schleife ausmessen, NEXT i& 'i = long integer t2! = TIMER PRINT t2! - t1!; "sec " RETURN MesseIFTHEN: PRINT "Messe IF/THEN : "; t1! = TIMER FOR i& = 1 TO 5000000 IF a% = 0 THEN 'IF THEN Methode ELSEIF a% = 2 THEN ELSE END IF NEXT i& t2! = TIMER PRINT t2! - t1! - Zc1!; "sec " RETURN MesseSELECTCASE: PRINT "Messe SELECT CASE: "; t1! = TIMER FOR i& = 1 TO 2000000 SELECT CASE A% 'SELECT CASE Methode CASE 0 CASE 1 CASE ELSE END SELECT NEXT i& t2! = TIMER PRINT t2! - t1! - Zc2!; "sec " RETURN MesseMATHEMATIK: PRINT "Messe MATHEMATIK : "; t1! = TIMER FOR i& = 1 TO 2000000 i% = i% + 100 'extrem einfache Aufgaben e& = e& * 2 e& = e& \ 2 i% = i% - 100 NEXT i& t2! = TIMER PRINT t2! - t1! - Zc2!; "sec " RETURN MesseSTRING: PRINT "Messe STRING's : "; t1! = TIMER FOR i& = 1 TO 2000 A$ = STRING$(20000, 32) A$ = RIGHT$(A$, 10000) + "Test" e% = INSTR(A$, "Test") A$ = "" NEXT i& t2! = TIMER PRINT t2! - t1! - Zc4!; "sec " RETURN MesseNUMPRINT: PRINT "Messe NUM-PRINT's "; t1! = TIMER FOR i& = 1 TO 100000 LOCATE , 1 PRINT "Messe NUM-PRINT's: "; i&; NEXT i& t2! = TIMER LOCATE , 20 PRINT t2! - t1! - Zc3!; "sec " RETURN MesseSTRPRINT: PRINT "Messe $$$-PRINT's "; t1! = TIMER FOR i& = 1 TO 100000 LOCATE , 1 PRINT "Messe $$$-PRINT's: "; NEXT i& t2! = TIMER LOCATE , 20 PRINT t2! - t1! - Zc3!; "sec " RETURN '***************************************************************** ' Hier nun die Routine zum Ausschalten des Coprozessors '***************************************************************** SUB Copro(Switch$) SELECT CASE UCASE$(Switch$) CASE "AUS", "OFF", "-" ! mov ax, &h0040 ! mov es, ax ! mov ax, word ptr es:[&h10] ! and ax, &b1111111111111101 ! mov word ptr es:[&h10], ax CASE "EIN", "ON", "+" ! mov ax, &h0040 ! mov es, ax ! mov ax, word ptr es:[&h10] ! or ax, &b0000000000000010 ! mov word ptr es:[&h10], ax END SELECT END SUB