3. PowerBASIC and the CoProcessor
3.1. Does PowerBASIC support a CoProcessor?
3.2. Which Floatingpointlibrary is the right one?
3.3. Does the CoProcessor work with $FLOAT PROCEDURE, too?
3.4. Which PowerBASIC-Functions are affected?
3.5. Possible reasons for the CoProcessor-Effect
3.6. PowerBASIC-Benchmark Source
3.1. Does PowerBASIC support a CoProcessor?
The answer is simply YES. The Compileroptions already have the
possibility to choose three different Floatingpointlibraries. There
are some Hooks when working with the CoPorcessor under PowerBASIC,
which will be shown here so that you can develop faster hopefully only
cleanly running programs.
3.2. Which Floatingpointlibrary is the right one?
PowerBASIC has a total of three Floatingpointlibraries:
- $FLOAT EMULATE
This is the DEFAULT-Library an usually uin use 95 % of the time.
She has the power to automatically support the i87, if such a
CoProcessor has been found. The huge problem is on the upper hand:
PowerBASIC has to test for the CoProcessor all of the time and is
slowed down a lot if NO i87 is installed.
- $FLOAT PROCEDURE
This Library is fastest when no CoProcessor is available.
- $FLOAT NPX
This Library is top when a i87 is available.
3.3. Does the CoProcessor work with $FLOAT PROCEDURE, too?
The answer here is YES, too. Even if PowerBASIC did not implement the
CoProcessorsupportroutines, the Source below proves that it does. The
riddles answer lies in the PowerBASIC-Runtime-Library, which supports
the i87 from beginning on. That is why the speed advantages can't be
generalized.
3.4. Which PowerBASIC-Routines are affected?
The following internal PowerBASIC-Functions are affected. Measures
have shown that SELECT CASE needs 5 seconds with the i87. Under the
same cirumstances (but without i87) SELECT CASE can need 200 seconds
($FLOAT EMULATE). The can be an extreme speedup with $FLOAT PROCEDURE
(only 35 seconds).
All in one you can say: SELECT CASE should not be used in time
critical routines!
Same, even if not as bad, is the PRINT-Output of numerical Values.
3.5. Possible reasons for the CoProcessor-Effect
As I see it this effect has natural causes, because all effected
commands have to work with the new 80-Number-System. It seems that the
programmers of PowerBASIC tried to compensate the additionally needed
time by using the CoProcessor. And it seems that it worked quite good
for them when a CoProcessor is available. On the other side there is
the question why the Compiler doesn't optimize it further when only
the normal 16/32-Bit numbers are used.
3.6. PowerBASIC-Benchmark Source
This source shall show you the connection between the previous
paragraphs. It is best if you just compile it and then try around a
bit.
Source:
REM *****************************************************************
REM
REM PBBENCH.EXE - Performance-Measuringprogram for PowerBASIC
REM
REM To test the differences in speed of different
REM PowerBASIC-Commands in connection with used Floatingpoint-
REM libraries when using or not using a CoProcessor
REM
REM Copyright: Thomas Gohel & Andras Hoeffken Version 2.10
REM All rights reserved
REM
REM -----------------------------------------------------------------
REM
REM Important Notice:
REM For reliable Maesures the Porcessor must be in REAL-Mode.
REM There may not be any TSRs, no KEYB.COM, SMARTDRV.EXE or
REM other.
REM Important:
REM For reliable Measures the program will have to be started
REM more than once and an avergae must be built.
REM
REM Users of 486/586 or 286/386 Processors with CoProcessor can
REM turn the x87 CoPro off in PowerBASIC with the in this Source
REM implemented listing.
REM
REM ***************************************************************
REM
$COMPILE EXE "PBBENCH.EXE"
$CPU 80386
$LIB ALL OFF
REM $FLOAT NPX ' for Computers with CoProzessor
' (fastest)
REM $FLOAT PROCEDURE ' for Computers without CoProzessor
' (not recommended)
REM $FLOAT EMULATE ' Automatic aupport (Extremly slow
' without CoProcessor)
REM $DEBUG MAP OFF
PRINT
PRINT "Performance-Testprogram for PowerBASIC";:
PRINT TAB(58); "(c) A.Hoeffken/Th.Gohel";:
PRINT TAB(68); "Version 2.10";:
PRINT STRING$(80,"-");
PRINT
a% = 1 ' some Variables
i% = 1234 ' -"-
e& = 12345678 ' -"-
REM Zc1! fuer 5000000-Schleifen ; To take out the time for the
REM Zc2! fuer 2000000-Schleifen ; FOR/NEXT-Loops
REM Zc3! fuer 100000-Schleifen
REM Zc4! fuer 2000-Schleifen
IF pbvnpx > 0 THEN
PRINT "CoProcessor " + CHR$(pbvnpx+48) + "87 found!"
PRINT
PRINT "Shoulod the CoProcessor be turned of for next";
PRINT "measure (Y/N)?"
BEEP
A$ = UCASE$(INPUT$(1))
IF A$ = "Y" THEN CoPro "AUS"
ELSE
PRINT "no CoProcessor found!"
PRINT
PRINT "Should the CoProcessor be turned on for the next";
PRINT "measure (Y/N)?"
PRINT
PRINT "Note: Turning on a not existing CoProcessor";
PRINT "will cause a crash!"
BEEP
A$ = UCASE$(INPUT$(1))
IF A$ = "Y" THEN CoPro "EIN"
END IF
PRINT
GOSUB HoleZeitKonstanten
GOSUB MesseFORNEXT
GOSUB MesseIFTHEN
GOSUB MesseSELECTCASE
GOSUB MesseMATHEMATIK
GOSUB MesseSTRING
GOSUB MesseNUMPRINT
GOSUB MesseSTRPRINT
PRINT
END
'***********************************************
' Get the Timeconstants for the different tests
'***********************************************
HoleZeitKonstanten:
PRINT "Messung der Zeitkonstanten ";
t1! = TIMER
FOR i& = 1 TO 2000 ' Time for 2000-Loops
NEXT i&
t2! = TIMER
Zc4! = t2! - t1!
PRINT ".";
t1! = TIMER
FOR i& = 1 TO 5000000 ' Time for 5-Mio-Loops
NEXT i&
t2! = TIMER
Zc1! = t2! - t1!
PRINT ".";
t1! = TIMER
FOR i& = 1 TO 100000 ' Time for 100000-Loops
NEXT i&
t2! = TIMER
Zc3! = t2! - t1!
PRINT "."
t1! = TIMER
FOR i& = 1 TO 2000000 ' Time for 2-Mio-Loops
NEXT i&
t2! = TIMER
Zc2! = t2! - t1!
RETURN
MesseFORNEXT:
PRINT "Testing FOR/NEXT : ";
t1! = TIMER
FOR i& = 1 TO 5000000 'Get 5-Millions-Loop
NEXT i& 'i = long integer
t2! = TIMER
PRINT t2! - t1!; "sec "
RETURN
MesseIFTHEN:
PRINT "Testing IF/THEN : ";
t1! = TIMER
FOR i& = 1 TO 5000000
IF a% = 0 THEN 'IF THEN Method
ELSEIF a% = 2 THEN
ELSE
END IF
NEXT i&
t2! = TIMER
PRINT t2! - t1! - Zc1!; "sec "
RETURN
MesseSELECTCASE:
PRINT "Testing SELECT CASE: ";
t1! = TIMER
FOR i& = 1 TO 2000000
SELECT CASE A% 'SELECT CASE Method
CASE 0
CASE 1
CASE ELSE
END SELECT
NEXT i&
t2! = TIMER
PRINT t2! - t1! - Zc2!; "sec "
RETURN
MesseMATHEMATIK:
PRINT "Testing MATHEMATIC : ";
t1! = TIMER
FOR i& = 1 TO 2000000
i% = i% + 100 'extremly simple Calculations
e& = e& * 2
e& = e& \ 2
i% = i% - 100
NEXT i&
t2! = TIMER
PRINT t2! - t1! - Zc2!; "sec "
RETURN
MesseSTRING:
PRINT "Testing 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 "Testing NUM-PRINT's ";
t1! = TIMER
FOR i& = 1 TO 100000
LOCATE , 1
PRINT "Testing NUM-PRINT's: "; i&;
NEXT i&
t2! = TIMER
LOCATE , 20
PRINT t2! - t1! - Zc3!; "sec "
RETURN
MesseSTRPRINT:
PRINT "Testing $$$-PRINT's ";
t1! = TIMER
FOR i& = 1 TO 100000
LOCATE , 1
PRINT "Testing $$$-PRINT's: ";
NEXT i&
t2! = TIMER
LOCATE , 20
PRINT t2! - t1! - Zc3!; "sec "
RETURN
'**********************************************
' Here is a routine to turn off the CoProcessor
'**********************************************
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