Author Topic: Copying arrays FOR vs _MEMCOPY  (Read 168 times)

Copying arrays FOR vs _MEMCOPY
« on: July 08, 2018, 06:44:58 PM »
Hi Guys

Learning  _MEM and its cousins _MEM() _MEMPUT _MEMGET _MEMCOPY _MEMNEW etc etc
seeing how to make a copy of array1 into array2 and following Steve's Wiki instructions
i wrote this code...
but on my TOSHIBA the time that I get is the same with the two methods, while surely the code more simple is _MEM.
Here the code
Code: [Select]


DIM a(100, 100) AS INTEGER
DIM b(100, 100) AS INTEGER

PRINT " COPY Array by FOR"
oldt1 = TIMER
SLEEP 2
initaz
showarray
SLEEP 2
copyArrayFor
showarray
SLEEP 2
oldt1 = TIMER - oldt1
PRINT oldt1
SLEEP 4
PRINT " COPY Array by _MEMCOPY"
oldt2 = TIMER
SLEEP 2
initaz
showarray
SLEEP 2
CopyArrayMEM
showarray
SLEEP 2
oldt2 = TIMER - oldt2
PRINT oldt2
SLEEP 2
PRINT "CopyFor = "; oldt1; " Copy_MEM = "; oldt2
END


SUB initaz
    SHARED a() AS INTEGER, b() AS INTEGER
    '--INITIALIZTION
    PRINT "INITALIZATION"
    FOR i1 = 0 TO 100
        FOR i2 = 0 TO 100
            b(i1, i2) = i1
            a(i1, i2) = 999
        NEXT
    NEXT
END SUB

SUB showarray
    SHARED a() AS INTEGER, b() AS INTEGER
    PRINT "SHOWING ARRAYS  B   A "
    FOR i1 = 0 TO 100
        FOR i2 = 0 TO 100
            PRINT b(i1, i2), a(i1, i2)
        NEXT
    NEXT
END SUB

SUB copyArrayFor
    SHARED a() AS INTEGER, b() AS INTEGER
    'copy array a to array b one index at a time:
    'FOR...NEXT|
    FOR i1 = 0 TO 100
        'FOR...NEXT|
        FOR i2 = 0 TO 100
            b(i1, i2) = a(i1, i2)
        NEXT
    NEXT
END SUB

SUB CopyArrayMEM
    SHARED a() AS INTEGER, b() AS INTEGER
    'copy array a to array b in memory instantly:

    DIM ma AS _MEM: ma = _MEM(a()) 'place array data into blocks
    DIM mb AS _MEM: mb = _MEM(b())
    _MEMCOPY ma, ma.OFFSET, ma.SIZE TO mb, mb.OFFSET
    _MEMFREE ma: _MEMFREE mb 'clear the memory when done
END SUB

Well, surely there is a better code to use _MEM. But How?


Offline SMcNeill

  • QB64 Developer
Re: Copying arrays FOR vs _MEMCOPY
« Reply #1 on: July 08, 2018, 08:00:10 PM »
The problem here isn't in the copying routines; the problem is with the method used to time the copying...

Lots of SLEEP statements, along with the initialization of the first array, and then printing to the screen... All these things take up time which makes it hard to see what, if any, change the switch from FOR to _MEMCOPY does for your program.

Taking the SLEEP, initialize, and PRINT statements out, and just timing the copy routines themselves, and changing the routines to work off a larger loop limit to highlight the differences, and what we see is the following:

Code: [Select]

CONST TestLimit = 10000
DIM a(TestLimit, TestLimit) AS INTEGER
DIM b(TestLimit, TestLimit) AS INTEGER
DIM SHARED ma1 AS _MEM
DIM SHARED mb1 AS _MEM


PRINT " COPY Array by FOR"
initaz
oldt1 = TIMER(0.001)
copyArrayFor
'showarray
oldt1 = TIMER(0.001) - oldt1
PRINT oldt1

PRINT " COPY Array by _MEMCOPY"
initaz
oldt2 = TIMER(0.001)
CopyArrayMEM
'showarray
oldt2 = TIMER(0.001) - oldt2
PRINT oldt2

PRINT "CopyFor = "; oldt1; " Copy_MEM = "; oldt2

END


SUB initaz
    SHARED a() AS INTEGER, b() AS INTEGER
    '--INITIALIZTION
    PRINT "INITALIZATION"
    FOR i1 = 0 TO TestLimit
        FOR i2 = 0 TO TestLimit
            b(i1, i2) = i1
            a(i1, i2) = 999
        NEXT
    NEXT
END SUB

SUB showarray
    SHARED a() AS INTEGER, b() AS INTEGER
    PRINT "SHOWING ARRAYS  B   A "
    FOR i1 = 0 TO TestLimit
        FOR i2 = 0 TO TestLimit
            PRINT b(i1, i2), a(i1, i2)
        NEXT
    NEXT
END SUB

SUB copyArrayFor
    SHARED a() AS INTEGER, b() AS INTEGER
    'copy array a to array b one index at a time:
    'FOR...NEXT|
    FOR i1 = 0 TO TestLimit
        'FOR...NEXT|
        FOR i2 = 0 TO TestLimit
            b(i1, i2) = a(i1, i2)
        NEXT
    NEXT
END SUB

SUB CopyArrayMEM
    SHARED a() AS INTEGER, b() AS INTEGER
    'copy array a to array b in memory instantly:

    DIM ma AS _MEM: ma = _MEM(a()) 'place array data into blocks
    DIM mb AS _MEM: mb = _MEM(b())
    _MEMCOPY ma, ma.OFFSET, ma.SIZE TO mb, mb.OFFSET
    _MEMFREE ma: _MEMFREE mb 'clear the memory when done
END SUB

7.7 seconds for the FOR LOOP to copy the arrays.
0.03 seconds for the _MEMCOPY to do its thing.

I think that shows a good comparison of which one might be a little more faster for our programs. 

Re: Copying arrays FOR vs _MEMCOPY
« Reply #2 on: July 09, 2018, 07:43:26 AM »
Thanks Steve

I must agree with you that I have done a SLEEPed use of _MEM...
:-)
IMHO the whole structure of code wins over single instructions

Thanks again

Re: Copying arrays FOR vs _MEMCOPY
« Reply #3 on: July 09, 2018, 09:29:25 PM »
Hi Steve

agreeing about the speedy of _MEM and the slowness of FOR...NEXT
here I post a code to show the one situation on which I think coders must prefer FOR...NEXT to _MEM
Code: [Select]

OPTION BASE 1
REDIM a(5, 3) AS INTEGER
DIM b(UBOUND(a, 1), UBOUND(a, 2)) AS INTEGER

initaz
PRINT "Array A  ";
showarray a()
PRINT " Array B  ";
showarray b()
SLEEP 2
PRINT "Saving orginal array data "
copyArray a(), b()
showarray b()
PRINT "press a key";: SLEEP: CLS
PRINT " REDIM array A with _PRESERVE  "
REDIM _PRESERVE a(7, 6) AS INTEGER
showarray a()
showarray b()
PRINT "Restoring original array data into array A "
copyArray b(), a()
showarray a()
PRINT " Garbage by _PRESERVE feature "
PRINT "press a key";: SLEEP: CLS
' to fix _PRESERVE  we must not use _PRESERVE
PRINT " Redim Array A and NO _preserve "
REDIM a(8, 7) AS INTEGER
showarray a()
showarray b()
' no clear no erase because they take down dimensions of the array
PRINT " Restoring original array data into array A "
copyArray b(), a()
showarray a()
showarray b()
PRINT "Press a key ": SLEEP: CLS
PRINT " Now Redim A with NO _PRESERVE"
REDIM a(7, 6) AS INTEGER
showarray a()
showarray b()
PRINT " Restoring data using CopyArrayFOR "
CopyArrayFor b(), a()
showarray a()
showarray b()

END


SUB initaz
    SHARED a() AS INTEGER, b() AS INTEGER
    '--INITIALIZATION
    PRINT "INITIALIZATION"
    FOR i1 = 1 TO UBOUND(a, 1)
        FOR i2 = 1 TO UBOUND(a, 2)
            b(i1, i2) = 999
            a(i1, i2) = i1
        NEXT
    NEXT
END SUB

SUB showarray (al() AS INTEGER)
    PRINT "SHOWING ARRAYS  "
    FOR i1 = 1 TO UBOUND(al, 1)
        FOR i2 = 1 TO UBOUND(al, 2)
            PRINT al(i1, i2); "-";
        NEXT
        _DELAY .5
        PRINT
    NEXT
    PRINT
END SUB

SUB copyArray (S() AS INTEGER, D() AS INTEGER)

    ' COPYARRAY (ArraySource(), ArrayDest())
    'copy array a1 to array b1 using _MEM functions:

    PRINT " COPYING ARRAY..."
    DIM mD AS _MEM, mS AS _MEM
    mD = _MEM(D())
    mS = _MEM(S())
    ' _MEMPUT mD, mD.OFFSET, S()  ' ALSO THIS INSTRUCTION GIVES THE SAME RESULTS....
    _MEMCOPY mS, mS.OFFSET, mS.SIZE TO mD, mD.OFFSET
    _MEMFREE mD: _MEMFREE mS
    PRINT "END COPY!"
END SUB

SUB CopyArrayFor (S() AS INTEGER, D() AS INTEGER)
    '-- COPY ARRAY USING FOR CICLES
    PRINT "COPY ARRAY USING FOR CICLES"
    FOR i1 = 1 TO UBOUND(s, 1)
        FOR i2 = 1 TO UBOUND(s, 2)
            D(i1, i2) = S(i1, i2)
        NEXT
    NEXT
END SUB

This code try to solve _PRESERVE issue using a manual function of copy and paste of old array in new array.
here _delay and SLEEP are used to show output, no speed of performance but rightness of results of operations of code is the cutoff to choose method to copy array....

seeing how _MEM is fast I wish that it is again a my poor code structure to give me these results...but it seems that _MEM instructions duplicate _PRESERVE results.
Thanks to read, waiting feedback.