basicqbasicqb64

Loop optimization in QB64


Have a loop in QB64 concerning loop optimization:

DIM N AS DOUBLE, X(100000000) AS DOUBLE
T! = TIMER
FOR N = 1 to 100000000
    IF X(N) THEN
        PRINT X(N)
        EXIT FOR
    END IF
NEXT
PRINT TIMER - T!

is it any faster than:

DIM N AS DOUBLE, X(100000000) AS DOUBLE
T! = TIMER
FOR N = 1 to 100000000
    IF X(N) <> 0  THEN
        PRINT X(N)
        EXIT FOR
    END IF
NEXT
PRINT TIMER - T!

EDITED: 09-18-2018 to include variable types


Solution

  • I written this code to evaluate your test:

    REM Delete REM to enable console runs
    REM $CONSOLE:ONLY
    REM _DEST _CONSOLE
    
    DIM SHARED N AS DOUBLE, X(100000000) AS DOUBLE
    
    S# = 0: ZC% = 0
    T% = 10
    IF COMMAND$ <> "" THEN
        T% = VAL(COMMAND$)
    END IF
    
    IF T% > 999 THEN T% = 999
    
    FOR I% = 1 TO T%
        A# = TRYA
        B# = TRYB
    
        D# = A# - B#
        PRINT USING "Case A ... : #.########"; A#
        PRINT USING "Case B ... : #.########"; B#
        PRINT USING "Diff ..... : #.########"; D#;
    
        A$ = ""
        IF ABS(D#) < 0.00000001 THEN
            ZC% = ZC% + 1
            A$ = "*"
        END IF
    
        S# = S# + A# - B#
    
        PRINT A$
        PRINT
    
        REM INKEY$ doesn't work in console mode!
        A$ = INKEY$
        IF A$ = CHR$(27) THEN
            I% = I% + 1: EXIT FOR
        END IF
    NEXT
    
    PRINT USING "Avrg A - B : #.########"; S# / (I% - 1)
    PRINT USING "0 diff:### on ### tryes"; ZC%, (I% - 1)
    PRINT
    
    PRINT "Hit a key to exit!"
    REM INPUT$ doesn't work in console mode!
    A$ = INPUT$(1)
    SYSTEM
    
    
    FUNCTION TRYA#
        T# = TIMER
        FOR N = 1 TO 100000000
            IF X(N) THEN
                PRINT X(N)
                EXIT FOR
            END IF
        NEXT
        A# = TIMER - T#
    
        TRYA = A#
    END FUNCTION
    
    FUNCTION TRYB#
        T# = TIMER
        FOR N = 1 TO 100000000
            IF X(N) <> 0 THEN
                PRINT X(N)
                EXIT FOR
            END IF
        NEXT
        A# = TIMER - T#
    
        TRYB = A#
    END FUNCTION
    

    The two different routines are inserted into two functions: TRYA and TRYB.

    I launched this SW with a loop that runs 999 times the functions and the result is:

    Avrg. A - B: 0.00204501
    0 diff:359 on 999 tryes
    

    then I launched with a 10 times loop and the result is:

    Avrg. A - B: -.01640625
    0 diff:  1 on  10 tryes
    

    then I launched with a 15 times loop and the result is:

    Avrg. A - B: 0.00026042
    0 diff:  5 on  15 tryes
    

    Cause we launch the SW in a multi-thread ambient I don't believe this is a very good test, but there's some results:

    1. In two cases the results of no difference (0 diff) is a third of all loops.
    2. In two cases it seems the function TRYA is slower.
    3. In one case it seems the function TRYB is slower.

    Looking at these results, I think, we may consider the two functions equivalent!

    You obtain more than 10 loops running the code from command line (or modifying the command$ parameter into the QB64 menu) as:

    # ./test n

    Where n is the number of loops you desire.

    The SW was compiled using gcc with -O3 optimizations option. (To do this you have to modify the file [/opt/]qb64/internal/c/makeline_lnx.txt)