home *** CD-ROM | disk | FTP | other *** search
- _ACCESSING LARGE ARRAYS WITH X-ARRAY_
- by Barr E. Bauer
-
-
- [LISTING ONE]
-
- * Extended memory manipulation using X-arRAY Fortran Library.
- * Does the following: 1. allocates a 1 Mbyte real*4 array a(512,512); 2. loads
- * array a with real*4 values; 3. saves the data in array a to disk;
- * 4. allocates two 1 Mbyte real*4 arrays b and c; 5. loads data from file
- * (step 3) into array b; 6. scales all members of array b by 5.0; 7. does an
- * element-by-element array multiplication of arrays a and b, results into
- * array c; 8. sums all members of array c, reports results.
- * Compile with Microsoft Fortran 5.1 using:
- * fl /FPi87 /G2 example1.for putback.for bagit.for /link xarray
- * B. E. Bauer 3/20/92
-
- interface to subroutine a2axtd(i1,i2,i3,i4[VALUE],r1,i5,i6)
- integer*4 i1,i2,i3,i4,i5
- integer*2 i6
- real*4 r1
- end
-
- interface to subroutine sgtrnm(i1,i2,i3[VALUE],i4,r1,i5)
- integer*4 i1,i2,i3,i4
- integer*2 i5
- real*4 r1
- end
-
- interface to subroutine sptrnm(i1,i2,i3[VALUE],i4,r1,i5)
- integer*4 i1,i2,i3,i4
- integer*2 i5
- real*4 r1
- end
-
- interface to subroutine smprnm(i1,i2,i3[VALUE],i4[VALUE],
- + i5[VALUE],i6)
- integer*4 i1,i2,i3,i4,i5
- integer*2 i6
- end
-
- interface to subroutine ssmrnm(i1,i2,i3[VALUE],r1,i4)
- integer*4 i1,i2,i3
- real*4 r1
- integer*2 i4
- end
-
- include 'bagit.inc' ! error codes and other symbols
- integer*4 kb_total, kb_unallocated, number_allocations
- integer*4 memory_manager, required_memory, shortage
- integer*4 handle_array(1), key_array(1)
- integer*4 ARRAY_SIZE(ARRAY_DIM), allocated_array(1)
-
- integer*4 handle, key, key1, kb_allocated
- integer*4 bytes_moved, increment
- integer*4 keyb, keyc, handleb, handlec
- real*4 temp, a(SIZE)
- integer*2 return_status, eflag
- character*13 tempfile
- data tempfile /'tempfile.dat'C/ ! C string format
- data ARRAY_SIZE / SIZE, SIZE /
-
- * enable extended memory routine flashing
- call flashr(ON,LOWER_RIGHT,eflag)
- if (eflag .ne. 0) call bagit(FLASHR_ERROR)
- required_memory = 3*SIZE*SIZE*REAL4/1024 ! need 3 Mbytes
- * determine status of extended memory
- call inqxtd(kb_total, kb_unallocated, number_allocations,
- + memory_manager, handle_array, key_array,
- + allocated_array, return_status, eflag)
- if (eflag .ne. 0) call bagit(INQXTD_ERROR)
- if ((memory_manager .eq. 0) .or.
- + (memory_manager .gt. 2)) then
- call bagit(WRONG_MMANAGER)
- else if (memory_manager .eq. 1) then
- print *,'XMS in use'
- else
- print *,'Modified LIM in use'
- endif
- print *,'Extended memory available ',kb_unallocated,' kb'
- if (kb_unallocated .lt. required_memory) then
- shortage = required_memory - kb_unallocated
- print *,'insufficient memory, need',shortage,'kb'
- call bagit(STOPPING)
- endif
- * enough memory present, allocate memory for 1st array
- print *,'just ahead of memory allocation'
- ! allocate a 2D array of real*4 dimensioned 512 by 512
- call getxtd(ARRAY_DIM,ARRAY_SIZE,REAL4,XMS,handle,key,
- 1 kb_allocated,return_status, eflag)
- if (eflag .ne. 0) call bagit(GETXTD_ERROR)
- * load extended memory array (X,Y) with 1.0 using column vector approach
- print *,'at loading stage'
- key1 = key
- temp = 0.0
- increment = SIZE*REAL4
- do j = 1,SIZE
- do k = 1,SIZE
- a(k) = 1.0 ! fills the 1D array with values
- enddo
- ! move the 1D into extended memory by columns
- ! putback is a2axtd interfaced for
- ! conventional -> extended memory transfers
- call putback(1,SIZE,REAL4,a,key1,bytes_moved,eflag)
- if (eflag .ne. 0) call bagit(PUTBACK_ERROR)
- if (bytes_moved .ne. increment) then
- call bagit(PUTBACK_BADCNT)
- endif
- key1 = key1 + increment
- enddo
- * save a copy of this array to disk
- print *,'saving array to file'
- call a2fxtd(ARRAY_DIM,ARRAY_SIZE,REAL4,tempfile,key,
- + ibytes_moved,eflag)
- if (ibytes_moved.ne.SIZE*SIZE*REAL4) then
- call bagit(A2FXTD_BADCNT)
- endif
- if (eflag.ne.0) call bagit(A2FXTD_ERROR)
- * allocate extended memory for arrays b and c
- call getxtd(ARRAY_DIM,ARRAY_SIZE,REAL4,XMS,handleb,keyb,
- + kb_allocated,return_status, eflag)
- if (eflag .ne. 0) call bagit(GETXTD_ERROR)
- call getxtd(ARRAY_DIM,ARRAY_SIZE,REAL4,XMS,handlec,keyc,
- + kb_allocated,return_status, eflag)
- if (eflag .ne. 0) call bagit(GETXTD_ERROR)
- * read file into extended memory for array b
- print *,'reading tempfile'
- call f2axtd(ARRAY_DIM,ARRAY_SIZE,REAL4,tempfile,keyb,
- 1 ibytes_moved,eflag)
- if (eflag.ne.0) call bagit(F2AXTD_ERROR)
- if (ibytes_moved.ne.SIZE*SIZE*REAL4) then
- call bagit(F2AXTD_BADCNT)
- endif
- * scale array b by 5.0
- print *,'scaling array b elements by 5.0'
- call ssmrnm(ARRAY_DIM,ARRAY_SIZE,keyb,5.0,eflag)
- if (eflag.ne.0) call bagit(SSMRNM_ERROR)
- * element-by-element mult of a and b, results to c
- print *,'ahead of array multiplication'
- call smprnm(2,ARRAY_SIZE,key,keyb,keyc,eflag)
- if (eflag .ne. 0) call bagit(SMPRNM_ERROR)
- * sum all elements of array c to check results by using column vectors to
- * bring data from extended into conventional memory, where sum is performed.
- key1 = keyc
- temp = 0.0
- increment = SIZE*REAL4
- do j = 1,SIZE
- call a2axtd(1,SIZE,REAL4,key1,a,bytes_moved,eflag)
- if (eflag.ne.0) call bagit(A2AXTD_ERROR)
- if (bytes_moved.ne.increment) call bagit(A2AXTD_BADCNT)
- do i=1,SIZE
- temp = temp + a(i)
- enddo
- key1 = key1 + increment ! advance to next column vector
- enddo
- print *,'done, sum = ',temp,' (correct = 1310720.000000)'
- * done, remove all allocations through ENDXTD in bagit
- call bagit(DONE)
- stop
- end
-
-
- [LISTING TWO]
-
- * Performs a sum reduction first using column vector moves then individual
- * element accesses
- * Compile with Microsoft Fortran 5.1
- * fl /FPi87 /G2 example1.for putback.for bagit.for /link xarray
- * B. E. Bauer 3/20/92
- *
- interface to subroutine a2axtd(i1,i2,i3,i4[VALUE],r1,i5,i6)
- integer*4 i1,i2,i3,i4,i5
- integer*2 i6
- real*4 r1
- end
-
- interface to subroutine sgtrnm(i1,i2,i3[VALUE],i4,r1,i5)
- integer*4 i1,i2,i3,i4
- integer*2 i5
- real*4 r1
- end
-
- interface to subroutine sptrnm(i1,i2,i3[VALUE],i4,r1,i5)
- integer*4 i1,i2,i3,i4
- integer*2 i5
- real*4 r1
- end
-
- include 'bagit.inc'
-
- integer*4 kb_total, kb_unallocated, number_allocations
- integer*4 memory_manager, required_memory, shortage
- integer*4 handle_array(1), key_array(1), allocated_array(1)
- integer*4 ARRAY_SIZE(2)
-
- integer*4 handle, key, key1, kb_allocated, increment
- integer*4 bytes_moved, index(2), keyj
-
- real*4 temp, a(SIZE), arrj(SIZE)
- integer*2 return_status, eflag
-
- data ARRAY_SIZE / SIZE, SIZE / ! 2D 512x512 array used
- * enable console flashing when extended memory is accessed
- call flashr(1,3,eflag)
- if (eflag .ne. 0) call bagit(FLASHR_ERROR)
- required_memory = SIZE*SIZE*REAL4/1024
- * check for adequate XMS memory, quit if inadequate
- call inqxtd(kb_total, kb_unallocated, number_allocations,
- + memory_manager, handle_array, key_array,
- + allocated_array, return_status, eflag)
- if (eflag.ne.0) call bagit(INQXTD_ERROR)
- if (required_memory .gt. kb_unallocated) call bagit(NOT_ENOUGH)
- * allocate a 512 by 512 array of real*4
- print *,'just ahead of memory allocation'
- call getxtd(2,ARRAY_SIZE,REAL4,XMS,handle,key,
- 1 kb_allocated,return_status, eflag)
- if (eflag .ne. 0) call bagit(GETXTD_ERROR)
- * load extended memory array (X,Y) using column vectors
- print *,'at loading stage'
- key1 = key
- temp = 0.0
- increment = SIZE*REAL4
- do j = 1,SIZE
- do k = 1,SIZE
- a(k) = float(k) + float(SIZE*(j-1))
- enddo
- call putback(1,SIZE,REAL4,a,key1,bytes_moved,eflag)
- if (eflag .ne. 0) call bagit(PUTBACK_ERROR)
- if (bytes_moved .ne. increment) then
- call bagit(PUTBACK_BADCNT)
- endif
- key1 = key1 + increment
- enddo
- * column vector summation
- print *,'start column vector sum reduction'
- sum_col = 0.0
- chunk = SIZE*REAL4
- do j=1,SIZE
- keyj = key + chunk*(j-1) ! address arithmetic
- ! put (,j) into arrj
- call a2axtd(1,SIZE,REAL4,keyj,arrj,bytes_moved,eflag)
- if (eflag.ne.0) call bagit(A2AXTD_ERROR)
- if (bytes_moved.ne.chunk) call bagit(A2AXTD_BADCNT)
- do k=1,SIZE ! process the column vector
- sum_col = sum_col +arrj(k)
- enddo
- enddo
- print *,'done with column vector sum reduction'
- * individual element access
- print *,'start individual access sum reduction'
- sum_ind = 0.0
- do i=1,SIZE
- do j=1,SIZE
- index(1)=i ! row of element
- index(2)=j ! column of element
- ! get the element into retval
- call sgtrnm(2,ARRAY_SIZE,key,index,retval,eflag)
- if (eflag.ne.0) call bagit(SGTRNM_ERROR)
- sum_ind = sum_ind + retval
- enddo
- enddo
- print *,'done with individual access sum reduction'
- print *,'column sum =',sum_col,', individual sum =',sum_ind
- call bagit(DONE)
- stop
- end
-
-
-
-
- [LISTING THREE]
-
- * Triangular array manipulation of a single 1 Mbyte real*4 array arr(512,512)
- * using X-arRAY routines
- * Does the following:
- * do j=1,512
- * do k = 1, j-1
- * do i = k+1, 512
- * arr(i,j) = arr(i,j) + arr(i,k) * arr(k,j)
- * enddo
- * enddo
- * enddo
- * Compile in Microsoft Fortran 5.1 using:
- * fl /FPi87 /G2 example2.for putback.for bagit.for /link xarray
- * B. E. Bauer 3/20/92
- *
- interface to subroutine a2axtd(i1,i2,i3,i4[VALUE],r1,i5,i6)
- integer*4 i1,i2,i3,i4,i5
- integer*2 i6
- real*4 r1
- end
-
- interface to subroutine sgtrnm(i1,i2,i3[VALUE],i4,r1,i5)
- integer*4 i1,i2,i3,i4
- integer*2 i5
- real*4 r1
- end
-
- interface to subroutine sptrnm(i1,i2,i3[VALUE],i4,r1,i5)
- integer*4 i1,i2,i3,i4
- integer*2 i5
- real*4 r1
- end
-
- include 'bagit.inc'
-
- integer*4 kb_total, kb_unallocated, number_allocations
- integer*4 memory_manager, required_memory
- integer*4 handle_array(1), key_array(1), allocated_array(1)
- integer*4 ARRAY_SIZE(ARRAY_DIM)
-
- integer*4 handle, key, key1, kb_allocated, increment
- integer*4 bytes_moved, index(2), keyj, keyk
-
- real*4 temp, a(SIZE), arrj(SIZE), arrk(SIZE)
- integer*2 return_status, eflag
-
- data ARRAY_SIZE / SIZE, SIZE /
- call flashr(ON,LOWER_RIGHT,eflag)
- required_memory = SIZE*SIZE*REAL4/1024
- call inqxtd(kb_total, kb_unallocated, number_allocations,
- + memory_manager, handle_array, key_array,
- + allocated_array, return_status, eflag)
- if (eflag.ne.0) call bagit(INQXTD_ERROR)
- if (kb_unallocated .lt. required_memory) then
- call bagit(NOT_ENOUGH)
- endif
- * allocate 1 Mbyte of extended memory
- print *,'just ahead of memory allocation'
- call getxtd(ARRAY_DIM,ARRAY_SIZE,REAL4,XMS,handle,key,
- + kb_allocated,return_status, eflag)
- if (eflag .ne. 0) call bagit(GETXTD_ERROR)
- print *,'loading extended memory'
- key1 = key
- temp = 0.0
- increment = SIZE*REAL4
- do j = 1,SIZE
- do k = 1,SIZE
- a(k) = 0.00025
- enddo
- call putback(1,SIZE,REAL4,a,key1,bytes_moved,eflag)
- if (eflag .ne. 0) call bagit(PUTBACK_ERROR)
- if (bytes_moved .ne. increment) call bagit(PUTBACK_BADCNT)
- key1 = key1 + increment
- enddo
- * process triangular array
- print *,'processing triangular array'
- keyj = key
- keyk = key
- chunk = SIZE*REAL4
- do j=1,SIZE
- print *,'outer loop j = ',j
- ! get arr(x,j) from extended into arrj(x)
- call a2axtd(1,SIZE,REAL4,keyj,arrj,bytes_moved,eflag)
- if (eflag.ne.0) call bagit(A2AXTD_ERROR)
- if (bytes_moved.ne.chunk) call bagit(A2AXTD_BADCNT)
- do k=1,j-1
- keyk = key + (k-1)*chunk
- ! get arr(x,k) from extended into arrk(x)
- call a2axtd(1,SIZE,REAL4,keyk,arrk,bytes_moved,eflag)
- if (eflag.ne.0) call bagit(A2AXTD_ERROR)
- if (bytes_moved.ne.chunk) call bagit(A2AXTD_BADCNT)
- ! do the manipulation
- do i=k+1,SIZE
- arrj(i) = arrj(i) + arrk(i)*arrj(k)
- enddo
- enddo
- ! put arrj(x) back to extended memory
- call putback(1,SIZE,REAL4,arrj,keyj,bytes_moved,eflag)
- if (eflag.ne.0) call bagit(A2AXTD_ERROR)
- if (bytes_moved.ne.chunk) call bagit(A2AXTD_BADCNT)
- keyj = keyj + chunk
- enddo
- * sample selected members of the array in extended memory
- do i=1,SIZE,125
- do j=1,SIZE,125
- index(1)=i
- index(2)=j
- call sgtrnm(ARRAY_DIM,ARRAY_SIZE,key,index,retval,eflag)
- if (eflag.ne.0) call bagit(SGTRNM_ERROR)
- print *,i,j,retval
- enddo
- enddo
- call bagit(DONE)
- stop
- end
-
-
-
- [LISTING FOUR]
-
- * putback.for--interface a2axtd for conventional to extended memory block moves
- * B. E. Bauer 3/20/92
- *
- interface to subroutine a2axtd(i1,i2,i3,r1,i4[VALUE],i5,i6)
- integer*4 i1,i2,i3,i4,i5
- integer*2 i6
- real*4 r1
- end
-
- subroutine putback(i1,i2,i3,r1,i4,i5,i6)
- integer*4 i1, i2, i3, i4, i5
- real*4 r1(*)
- integer*2 i6
- call a2axtd(i1,i2,i3,r1,i4,i5,i6)
- return
- end
-
- [LISTING FIVE]
-
- * bagit.inc--symbols and declarations used for error handling and the examples.
- * B. E. Bauer 3/20/92
- *
- integer*4 INQXTD_ERROR,WRONG_MMANAGER,STOPPING,GETXTD_ERROR
- integer*4 PUTBACK_ERROR,PUTBACK_BADCNT,A2AXTD_BADCNT
- integer*4 A2AXTD_ERROR,A2FXTD_BADCNT,A2FXTD_ERROR
- integer*4 F2AXTD_ERROR,F2AXTD_BADCNT,SSMRNM_ERROR
- integer*4 SMPRNM_ERROR,NOT_ENOUGH,SGTRNM_ERROR
- integer*4 FLASHR_ERROR,DONE
-
- integer*4 ARRAY_DIM,REAL4,XMS,SIZE,ON,LOWER_RIGHT
-
- parameter (INQXTD_ERROR=1)
- parameter (WRONG_MMANAGER=2)
- parameter (STOPPING=3)
- parameter (GETXTD_ERROR=4)
- parameter (PUTBACK_ERROR=5)
- parameter (PUTBACK_BADCNT=6)
- parameter (A2AXTD_BADCNT=7)
- parameter (A2AXTD_ERROR=8)
- parameter (A2FXTD_BADCNT=9)
- parameter (A2FXTD_ERROR=9)
- parameter (F2AXTD_ERROR=10)
- parameter (F2AXTD_BADCNT=11)
- parameter (SSMRNM_ERROR=12)
- parameter (SMPRNM_ERROR=13)
- parameter (NOT_ENOUGH=14)
- parameter (SGTRNM_ERROR=15)
- parameter (FLASHR_ERROR=16)
- parameter (DONE=99)
-
- parameter (ARRAY_DIM = 2) ! 2D array
- parameter (REAL4 = 4) ! size of real*4
- parameter (XMS = -1) ! use available mmanager
- parameter (SIZE = 512) ! size of array
- parameter (ON = 1) ! convenient symbol
- parameter (LOWER_RIGHT = 3) ! where flashr flashes
-
-
-
- [LISTING SIX]
-
- * bagit.for--error handler. Prints an appropriate message then calls endxtd
- * to ensure allocations are freed.
- * B. E. Bauer 3/20/92
- *
- subroutine bagit(iflag)
- integer*4 iflag
- integer*2 return_status, eflag
-
- include 'bagit.inc'
-
- select case (iflag)
- case (INQXTD_ERROR)
- print *,'error reported by inqxtd'
- case (WRONG_MMANAGER)
- print *,'XMS or Mondified LIM memory manager not found'
- case (STOPPING)
- print *,'stopping...'
- case (GETXTD_ERROR)
- print *,'error reported by getxtd'
- case (PUTBACK_ERROR)
- print *,'error in putback(a2axtd)'
- case (PUTBACK_BADCNT)
- print *,'wrong number of bytes moved by putback(a2axtd)'
- case (A2AXTD_BADCNT)
- print *,'wrong number of bytes moved by a2axtd'
- case (A2AXTD_ERROR)
- print *,'error in a2axtd'
- case (A2FXTD_BADCNT)
- print *,'wrong number of bytes moved by a2fxtd'
- case (A2FXTD_ERROR)
- print *,'error in a2fxtd'
- case (F2AXTD_ERROR)
- print *,'error in f2axtd'
- case (F2AXTD_BADCNT)
- print *,'wrong number of bytes moved by f2axtd'
- case (SSMRNM_ERROR)
- print *,'error in ssmrnm (scalar multiply)'
- case (SMPRNM_ERROR)
- print *,'error in smprnm (el-by-el multiply)'
- case (NOT_ENOUGH)
- print *,'inadequate extended memory available'
- case (SGTRNM_ERROR)
- print *,'error in sgtrnm (real*4 get)'
- case (FLASHR_ERROR)
- print *,'error in flashr'
- case (DONE)
- print *,'freeing extended memory'
- end select
- call endxtd(return_status, eflag)
- stop 'done, exiting...'
- end
-
-