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

0 Members and 1 Guest are viewing this topic.

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Copying arrays FOR vs _MEMCOPY
« on: July 08, 2018, 05: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: QB64: [Select]
  1.  
  2.  
  3. DIM a(100, 100) AS INTEGER
  4. DIM b(100, 100) AS INTEGER
  5.  
  6. PRINT " COPY Array by FOR"
  7. oldt1 = TIMER
  8. initaz
  9. showarray
  10. copyArrayFor
  11. showarray
  12. oldt1 = TIMER - oldt1
  13. PRINT oldt1
  14. PRINT " COPY Array by _MEMCOPY"
  15. oldt2 = TIMER
  16. initaz
  17. showarray
  18. CopyArrayMEM
  19. showarray
  20. oldt2 = TIMER - oldt2
  21. PRINT oldt2
  22. PRINT "CopyFor = "; oldt1; " Copy_MEM = "; oldt2
  23.  
  24.  
  25. SUB initaz
  26.     SHARED a() AS INTEGER, b() AS INTEGER
  27.     '--INITIALIZTION
  28.     PRINT "INITALIZATION"
  29.     FOR i1 = 0 TO 100
  30.         FOR i2 = 0 TO 100
  31.             b(i1, i2) = i1
  32.             a(i1, i2) = 999
  33.         NEXT
  34.     NEXT
  35.  
  36. SUB showarray
  37.     SHARED a() AS INTEGER, b() AS INTEGER
  38.     PRINT "SHOWING ARRAYS  B   A "
  39.     FOR i1 = 0 TO 100
  40.         FOR i2 = 0 TO 100
  41.             PRINT b(i1, i2), a(i1, i2)
  42.         NEXT
  43.     NEXT
  44.  
  45. SUB copyArrayFor
  46.     SHARED a() AS INTEGER, b() AS INTEGER
  47.     'copy array a to array b one index at a time:
  48.     'FOR...NEXT|
  49.     FOR i1 = 0 TO 100
  50.         'FOR...NEXT|
  51.         FOR i2 = 0 TO 100
  52.             b(i1, i2) = a(i1, i2)
  53.         NEXT
  54.     NEXT
  55.  
  56. SUB CopyArrayMEM
  57.     SHARED a() AS INTEGER, b() AS INTEGER
  58.     'copy array a to array b in memory instantly:
  59.  
  60.     DIM ma AS _MEM: ma = _MEM(a()) 'place array data into blocks
  61.     DIM mb AS _MEM: mb = _MEM(b())
  62.     _MEMCOPY ma, ma.OFFSET, ma.SIZE TO mb, mb.OFFSET
  63.     _MEMFREE ma: _MEMFREE mb 'clear the memory when done
  64.  

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

Programming isn't difficult, only it's  consuming time and coffee

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Copying arrays FOR vs _MEMCOPY
« Reply #1 on: July 08, 2018, 07: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: QB64: [Select]
  1.  
  2. CONST TestLimit = 10000
  3. DIM a(TestLimit, TestLimit) AS INTEGER
  4. DIM b(TestLimit, TestLimit) AS INTEGER
  5.  
  6.  
  7. PRINT " COPY Array by FOR"
  8. initaz
  9. oldt1 = TIMER(0.001)
  10. copyArrayFor
  11. 'showarray
  12. oldt1 = TIMER(0.001) - oldt1
  13. PRINT oldt1
  14.  
  15. PRINT " COPY Array by _MEMCOPY"
  16. initaz
  17. oldt2 = TIMER(0.001)
  18. CopyArrayMEM
  19. 'showarray
  20. oldt2 = TIMER(0.001) - oldt2
  21. PRINT oldt2
  22.  
  23. PRINT "CopyFor = "; oldt1; " Copy_MEM = "; oldt2
  24.  
  25.  
  26.  
  27. SUB initaz
  28.     SHARED a() AS INTEGER, b() AS INTEGER
  29.     '--INITIALIZTION
  30.     PRINT "INITALIZATION"
  31.     FOR i1 = 0 TO TestLimit
  32.         FOR i2 = 0 TO TestLimit
  33.             b(i1, i2) = i1
  34.             a(i1, i2) = 999
  35.         NEXT
  36.     NEXT
  37.  
  38. SUB showarray
  39.     SHARED a() AS INTEGER, b() AS INTEGER
  40.     PRINT "SHOWING ARRAYS  B   A "
  41.     FOR i1 = 0 TO TestLimit
  42.         FOR i2 = 0 TO TestLimit
  43.             PRINT b(i1, i2), a(i1, i2)
  44.         NEXT
  45.     NEXT
  46.  
  47. SUB copyArrayFor
  48.     SHARED a() AS INTEGER, b() AS INTEGER
  49.     'copy array a to array b one index at a time:
  50.     'FOR...NEXT|
  51.     FOR i1 = 0 TO TestLimit
  52.         'FOR...NEXT|
  53.         FOR i2 = 0 TO TestLimit
  54.             b(i1, i2) = a(i1, i2)
  55.         NEXT
  56.     NEXT
  57.  
  58. SUB CopyArrayMEM
  59.     SHARED a() AS INTEGER, b() AS INTEGER
  60.     'copy array a to array b in memory instantly:
  61.  
  62.     DIM ma AS _MEM: ma = _MEM(a()) 'place array data into blocks
  63.     DIM mb AS _MEM: mb = _MEM(b())
  64.     _MEMCOPY ma, ma.OFFSET, ma.SIZE TO mb, mb.OFFSET
  65.     _MEMFREE ma: _MEMFREE mb 'clear the memory when done
  66.  

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. 
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: Copying arrays FOR vs _MEMCOPY
« Reply #2 on: July 09, 2018, 06: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
Programming isn't difficult, only it's  consuming time and coffee

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: Copying arrays FOR vs _MEMCOPY
« Reply #3 on: July 09, 2018, 08: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: QB64: [Select]
  1.  
  2. REDIM a(5, 3) AS INTEGER
  3. DIM b(UBOUND(a, 1), UBOUND(a, 2)) AS INTEGER
  4.  
  5. initaz
  6. PRINT "Array A  ";
  7. showarray a()
  8. PRINT " Array B  ";
  9. showarray b()
  10. PRINT "Saving orginal array data "
  11. copyArray a(), b()
  12. showarray b()
  13. PRINT "press a key";: SLEEP: CLS
  14. PRINT " REDIM array A with _PRESERVE  "
  15. showarray a()
  16. showarray b()
  17. PRINT "Restoring original array data into array A "
  18. copyArray b(), a()
  19. showarray a()
  20. PRINT " Garbage by _PRESERVE feature "
  21. PRINT "press a key";: SLEEP: CLS
  22. ' to fix _PRESERVE  we must not use _PRESERVE
  23. PRINT " Redim Array A and NO _preserve "
  24. REDIM a(8, 7) AS INTEGER
  25. showarray a()
  26. showarray b()
  27. ' no clear no erase because they take down dimensions of the array
  28. PRINT " Restoring original array data into array A "
  29. copyArray b(), a()
  30. showarray a()
  31. showarray b()
  32. PRINT "Press a key ": SLEEP: CLS
  33. PRINT " Now Redim A with NO _PRESERVE"
  34. REDIM a(7, 6) AS INTEGER
  35. showarray a()
  36. showarray b()
  37. PRINT " Restoring data using CopyArrayFOR "
  38. CopyArrayFor b(), a()
  39. showarray a()
  40. showarray b()
  41.  
  42.  
  43.  
  44. SUB initaz
  45.     SHARED a() AS INTEGER, b() AS INTEGER
  46.     '--INITIALIZATION
  47.     PRINT "INITIALIZATION"
  48.     FOR i1 = 1 TO UBOUND(a, 1)
  49.         FOR i2 = 1 TO UBOUND(a, 2)
  50.             b(i1, i2) = 999
  51.             a(i1, i2) = i1
  52.         NEXT
  53.     NEXT
  54.  
  55. SUB showarray (al() AS INTEGER)
  56.     PRINT "SHOWING ARRAYS  "
  57.     FOR i1 = 1 TO UBOUND(al, 1)
  58.         FOR i2 = 1 TO UBOUND(al, 2)
  59.             PRINT al(i1, i2); "-";
  60.         NEXT
  61.         _DELAY .5
  62.         PRINT
  63.     NEXT
  64.     PRINT
  65.  
  66. SUB copyArray (S() AS INTEGER, D() AS INTEGER)
  67.  
  68.     ' COPYARRAY (ArraySource(), ArrayDest())
  69.     'copy array a1 to array b1 using _MEM functions:
  70.  
  71.     PRINT " COPYING ARRAY..."
  72.     DIM mD AS _MEM, mS AS _MEM
  73.     mD = _MEM(D())
  74.     mS = _MEM(S())
  75.     ' _MEMPUT mD, mD.OFFSET, S()  ' ALSO THIS INSTRUCTION GIVES THE SAME RESULTS....
  76.     _MEMCOPY mS, mS.OFFSET, mS.SIZE TO mD, mD.OFFSET
  77.     _MEMFREE mD: _MEMFREE mS
  78.     PRINT "END COPY!"
  79.  
  80. SUB CopyArrayFor (S() AS INTEGER, D() AS INTEGER)
  81.     '-- COPY ARRAY USING FOR CICLES
  82.     PRINT "COPY ARRAY USING FOR CICLES"
  83.     FOR i1 = 1 TO UBOUND(s, 1)
  84.         FOR i2 = 1 TO UBOUND(s, 2)
  85.             D(i1, i2) = S(i1, i2)
  86.         NEXT
  87.     NEXT
  88.  
  89.  
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.

Programming isn't difficult, only it's  consuming time and coffee