 |
forums.silverfrost.com Welcome to the Silverfrost forums
|
| View previous topic :: View next topic |
| Author |
Message |
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8320 Location: Salford, UK
|
Posted: Fri Sep 26, 2008 4:47 pm Post subject: |
|
|
Hi John
We have considered the questions that you raise and suggest that the best way forward would be for you to send us a small program/project that illustrates the problems that you are encountering.
In the mean time here is a sample program that allocates about 2.8 GB on my machine
| Code: |
real(2),pointer::gib(:)
real(1) size
size=0.0
do
allocate(gib(10000000))
size = size+80000000
print*, size
enddo
end |
Regards
Paul |
|
| Back to top |
|
 |
JohnCampbell
Joined: 16 Feb 2006 Posts: 2629 Location: Sydney
|
Posted: Fri Sep 26, 2008 11:54 pm Post subject: |
|
|
Paul,
I emailed you the file big_new_memory.zip on 16 Sep to your hotmail account, which was the account you had previously advised for emailing sample programs. It is a small program with little code, but big arrays. It's a bit of a mess as there is a bit of commented out code, as I tried different ideas.
My example used explicit array sizeing with common or modules. After 1.85 gb of arrays, the executable generated gives "is not a valid Win32 application" error ?
I will try your example, using allocate. My big memory PC is at work.
What pool of memory does allocate get the big chunks of memory from ?
John |
|
| Back to top |
|
 |
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8320 Location: Salford, UK
|
Posted: Sat Sep 27, 2008 7:50 am Post subject: |
|
|
ALLOCATE ends up using the Windows API GlobalAlloc or HeapAlloc.
We will look at your sample code as soon as we can.
Paul |
|
| Back to top |
|
 |
JohnCampbell
Joined: 16 Feb 2006 Posts: 2629 Location: Sydney
|
Posted: Mon Sep 29, 2008 12:38 am Post subject: |
|
|
Paul,
I tried the allocate approach with real*8 arrays and it failed after 1.15gb.
the following is the commands I used to run it.
ftn95 big_alloc /lis /xref
slink big_alloc.obj /3gb /map:big_alloc.map /file:big_alloc.exe
| Code: |
! Last change: JDC 29 Sep 2008 9:00 am
! Program to test memory sizes
!
module large_array
!
real*10, parameter :: one = 1
real*10, parameter :: two = 2
real*10, parameter :: eight = 8
!
integer*4, parameter :: megabyte = 1024*1024/8
!
! Did not work if declared in module
! integer*4 array_a_size
! real*8, dimension(:), allocatable :: a8_array
!
end module large_array
use large_array
!
integer*4 array_a_size
real*8, dimension(:), allocatable :: a8_array
!
integer*4 i, m_100, m, ii
real*10 s1, s2, sa
character description*80
!
open (unit=98, file='big_array.log', position='append')
!
call date_time_label (98)
!
do ii = 1000,2500,50
!
array_a_size = ii * megabyte
sa = dble (array_a_size) * 8. / 1024./1024./1024.
write (description,1000) 'This test for 1 allocated array, memory allocated = ',sa,' gb'
call report (description)
!
allocate (a8_array(array_a_size))
call report (' array a allocated')
!
write (description,1001) 'initialising array A of ', array_a_size,' real*8 variables'
call report (description)
!
m_100 = (1024*1024/8)*100
m = m_100
do i = 1,array_a_size
m = m-1
if (m <= 0) then
s1 = dble(i) * eight / dble(1024)**3
write (description, 1004) s1
call report (description)
m = m_100
end if
a8_array(i) = i
end do
call report (' array a initialised')
!
sa = array_a_size
sa = sa*(sa+one)/two
!
s1 = 0
do i = 1,array_a_size
s1 = s1 + a8_array(i)
end do
write (description,1002) ' do Sum of array a = ',s1, s1-sa
call report (description)
!
s2 = sum (a8_array)
write (description,1002) ' Sum of array a = ',s2, s2-sa
call report (description)
!
deallocate (a8_array)
call report (' array a deallocated')
end do
!
1000 format (a,f0.3,a)
1001 format (a,b'zzz,zzz,zz#',a)
1002 format (a,es22.15,' (error=',es10.3,')')
1004 format ( f5.1,' gb initialised')
end
subroutine report (description)
!
! returns the time in the form hh:mm pm
!
character description*(*)
real*8 seconds
!
call get_run_time (seconds)
WRITE ( *,1011) seconds, trim (description)
WRITE (98,1011) seconds, trim (description)
!
RETURN
1011 FORMAT (f10.3,2x,a)
END
|
[/code]
Last edited by JohnCampbell on Mon Sep 29, 2008 12:41 am; edited 1 time in total |
|
| Back to top |
|
 |
JohnCampbell
Joined: 16 Feb 2006 Posts: 2629 Location: Sydney
|
Posted: Mon Sep 29, 2008 12:40 am Post subject: |
|
|
the post worked in preview, but clipped when sent. this is the rest of the code.
| Code: |
subroutine get_run_time (seconds)
!
! returns the elapsed time, accurate to .001 seconds (?)
!
real*8 seconds
!
CHARACTER date*8, time*10, zone*5
INTEGER values(8)
real*8 start_time, x
data start_time / -1 /
!
call DATE_AND_TIME (date, time, zone, values)
!
x = 60.0*60.0*values(5) &
+ 60.0*values(6) &
+ values(7) &
+ 0.001*values(8)
!
if (start_time < 0) start_time = x
seconds = x - start_time
RETURN
END
SUBROUTINE DATE_TIME_LABEL (LUNIT)
!
! Displays the date and time on file unit LUNIT
!
integer*4, intent (in) :: lunit
!
CHARACTER LABEL(12)*3, CBUF*22
STDCALL GETLOCALTIME 'GetLocalTime' (REF)
integer*2 ia(8), YEAR,MONTH
DATA LABEL / 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', &
& 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' /
!
call GetLocalTime (ia)
!
year = mod (ia(1),100)
month = ia(2)
!
WRITE (CBUF,1009) ia(4), LABEL(MONTH), YEAR, ia(5), ia(6), ia(7),ia(8)
1009 FORMAT (I2,'-',A3,'-',I2.2, i3,':',i2.2,':',i2.2,'.',i3.3)
!
WRITE (LUNIT,2001) CBUF
2001 FORMAT (/' ** ( THIS RUN DONE AT ',A,') **')
!
RETURN
!
END
|
|
|
| Back to top |
|
 |
JohnCampbell
Joined: 16 Feb 2006 Posts: 2629 Location: Sydney
|
Posted: Mon Sep 29, 2008 2:34 am Post subject: |
|
|
Paul,
I also tried various block sizes in your program with unusual results.
While 80mg blocks gives 2,768mb, the allocated memory reduces with bigger block sizes.
(> 597mg) 600mg blocks gives only 2 blocks and fails at only 1,887mb while 1,000mg blocks gives up to 2,097mb
1,200mg and above gives nothing !!
Unfortunately, I'm from old Fortran and am not familiar with pointers !
All this with FTN95_NEW_MEMORY
| Code: |
! Last change: JDC 29 Sep 2008 9:00 am
! Program to test memory sizes
!
real*8, pointer :: gib(:)
!
integer*4 i, alstat, block_size
integer*4, parameter :: mega_byte = 1024*1024/8
integer*8, parameter :: eight = 8
integer*8 size, b8
!
write (*,*) 'megabyte ?'
read (*,*) i
block_size = i*mega_byte ! defines 1 blocks
!
! block_size = 80*mega_byte ! defines 33 blocks 2,768,240,640 2,852m fail
! block_size = 200*mega_byte ! defines 12 blocks 2,516,582,400 2,726m fail
! block_size = 300*mega_byte ! defines 7 blocks 2,202,009,600 2,516m fail
! block_size = 400*mega_byte ! defines 5 blocks 2,097,152,000 2,516m fail
! block_size = 500*mega_byte ! defines 4 blocks 2,097,152,000 2,621m fail
! block_size = 550*mega_byte ! defines 3 blocks 1,730,150,400 2,306m fail
! block_size = 597*mega_byte ! defines 3 blocks 1,877,999,616 2,503m fail
! block_size = 600*mega_byte ! defines 2 blocks 1,258,291,200 1,887m fail
! block_size = 800*mega_byte ! defines 2 blocks 1,677,721,600 2,516m fail
! block_size = 1000*mega_byte ! defines 2 blocks 2,097,152,000 3,115m fail
! block_size = 1100*mega_byte ! defines 1 blocks 1,153,433,600 2,306m fail
!
! block_size = 1200*mega_byte ! defines no blocks
b8 = block_size
size = 0
!
do i = 1,1000
allocate (gib(block_size),stat=alstat)
size = size + eight*b8
print*, i, size, alstat
if (alstat /= 0) exit
end do
end
|
|
|
| Back to top |
|
 |
JohnCampbell
Joined: 16 Feb 2006 Posts: 2629 Location: Sydney
|
Posted: Mon Sep 29, 2008 5:05 am Post subject: |
|
|
Paul,
I again modified your example to allocate multiple real*8 arrays and test the gaps between them using LOC.
Using 312,000,000 byte chunks, the allocation started at about 258 mb,
it allocated 4 blocks from 258mb to 1448 mb
it then left a 41mb gap at 1449mb and
another 261mb gap at 1787 mb
finally 3 blocks from 2048mb to 2940 mb
Do you know why it started at 258mb and what are the 2 other gaps ?
I'd expect if I used 80mb blocks, there may be other gaps.
This also shows a maximum contiguous area of 1200 mb without any influence.
Presumably when we get arrays of 1.8gb, some of these gaps are moved around.
The following is the code I used, which gave these interesting results.
| Code: |
! Last change: JDC 29 Sep 2008 1:30 pm
! Program to test memory sizes
! Allocate the blocks then test for contiguous memory
!
! real*8, pointer :: gib(:)
real*8, allocatable, dimension(:) :: gib_1
real*8, allocatable, dimension(:) :: gib_2
real*8, allocatable, dimension(:) :: gib_3
real*8, allocatable, dimension(:) :: gib_4
real*8, allocatable, dimension(:) :: gib_5
real*8, allocatable, dimension(:) :: gib_6
real*8, allocatable, dimension(:) :: gib_7
real*8, allocatable, dimension(:) :: gib_8
!
integer*4 i, alstat, block_size
integer*4, parameter :: mega_byte = (1000*1000)/8 ! 10^6 looks better
integer*8 size_8
!
write (*,*) 'megabyte ?' ! 313 for all
read (*,*) i
block_size = i*mega_byte ! defines 1 blocks
!
i = 0
size_8 = 0
!
allocate (gib_1(block_size),stat=alstat)
call report (i, gib_1, size_8, block_size, alstat)
if (alstat /= 0) goto 100
!
allocate (gib_2(block_size),stat=alstat)
call report (i, gib_2, size_8, block_size, alstat)
if (alstat /= 0) goto 100
!
allocate (gib_3(block_size),stat=alstat)
call report (i, gib_3, size_8, block_size, alstat)
if (alstat /= 0) goto 100
!
allocate (gib_4(block_size),stat=alstat)
call report (i, gib_4, size_8, block_size, alstat)
if (alstat /= 0) goto 100
!
allocate (gib_5(block_size),stat=alstat)
call report (i, gib_5, size_8, block_size, alstat)
if (alstat /= 0) goto 100
!
allocate (gib_6(block_size),stat=alstat)
call report (i, gib_6, size_8, block_size, alstat)
if (alstat /= 0) goto 100
!
allocate (gib_7(block_size),stat=alstat)
call report (i, gib_7, size_8, block_size, alstat)
if (alstat /= 0) goto 100
!
allocate (gib_8(block_size),stat=alstat)
call report (i, gib_8, size_8, block_size, alstat)
if (alstat /= 0) goto 100
!
100 continue
end
! subroutine report (n, gib, size_8, block_size, alstat)
|
Last edited by JohnCampbell on Mon Sep 29, 2008 5:09 am; edited 1 time in total |
|
| Back to top |
|
 |
JohnCampbell
Joined: 16 Feb 2006 Posts: 2629 Location: Sydney
|
Posted: Mon Sep 29, 2008 5:06 am Post subject: |
|
|
Again there was too much code:
| Code: |
subroutine report (n, gib, size_8, block_size, alstat)
!
integer*4 n, block_size, alstat
real*8 gib(block_size)
integer*8 size_8
!
integer*8, parameter :: zero = 0
integer*8, parameter :: eight = 8
integer*8, parameter :: one_gb = 1024*1024*1024
integer*8 b8, m1, m2, m0, m_alloc, m_gap, two_gb, four_gb
intrinsic loc
save m0
!
b8 = block_size
n = n + 1
size_8 = size_8 + eight*b8
! print*, n, size_8, alstat
if (alstat /= 0) return
!
m1 = loc (gib(1))
m2 = loc (gib(block_size))
!
two_gb = one_gb + one_gb
four_gb = two_gb + two_gb
if (m1 < zero) m1 = m1 + four_gb
if (m2 < zero) m2 = m2 + four_gb
!
m2 = m2 + eight
m_alloc = (m2-m1)
m_gap = 0
if (n > 1) m_gap = m1 - m0
m0 = m2
!
write (*,1001) 'memory location', n, m1, m2, m_alloc, m_gap
1001 format (a,i3,2i12,i11, i10)
end subroutine
|
|
|
| Back to top |
|
 |
JohnCampbell
Joined: 16 Feb 2006 Posts: 2629 Location: Sydney
|
Posted: Tue Sep 30, 2008 9:28 am Post subject: |
|
|
Paul,
I again took your program and tried to extend the "cheating" on multiple allocates for pointer arrays, to test the memory availability. I put the program in as a subroutine, so that when it exits, I thought all the allocates would be automatically deallocated (fortran standard ?). This does not appear to work.
However with a block size of 20mb, it shows in more detail what areas of memory are not available. The program also appears to confirm that the /3gb switch is providing the 3gb of accessible memory.
I'm assuming the contiguous areas can be addressed as merged blocks. I will take the previous real*8 array program in an earlier post and confirm if this works.
It remains to be able to shift the "unavailable parts" to a better area to maximise the size of contiguous available memory. Isn't this what Slink does ?
| Code: |
! Last change: JDC 30 Sep 2008 9:53 am
!
call test_contiguous (20)
call test_contiguous (40) ! this call failed
call test_contiguous (80)
call test_contiguous (120)
call test_contiguous (200)
call test_contiguous (400)
call test_contiguous (600)
call test_contiguous (800)
end
subroutine test_contiguous (block_mb)
!
! subroutine to test memory sizes and contiguous allocation
!
integer*4 block_mb
!
real*8, pointer :: gib(:)
!
integer*4 i, alstat, block_size
integer*4, parameter :: mega_byte = 1024*1024/8
integer*8, parameter :: zero = 0
integer*8, parameter :: four = 4
integer*8, parameter :: eight = 8
integer*8, parameter :: one_gb = 1024*1024*1024
integer*8, parameter :: four_gb = one_gb*four
integer*8 size, b8, js,je
real*8 mgs, mge, mgg, mgl
!
write (*,*) 'Testing block size ',block_mb,'mb'
block_size = block_mb*mega_byte ! defines 1 block in real*8
!
b8 = block_size*eight
size = 0
mgl = 0 ! last end
!
do i = 1,1000
allocate (gib(block_size),stat=alstat)
! cumulative size (bytes)
size = size + b8
! start and end address (bytes)
js = loc(gib(1)) ; if (js < zero) js = js + four_gb
je = loc(gib(block_size)) ; if (je < zero) je = je + four_gb
! start and end address (mb)
mgs = dble(js) / 1024./1024.
mge = dble(je) / 1024./1024.
! gap size (mb)
mgg = mgs - mgl
mgl = mge
write (*,2001) i, size, alstat, js,je, mgs, mgl, mgg
2001 format (i5, i12, i5, 2i12, 3f10.2)
if (alstat /= 0) exit
end do
! hopefully release allocated memory
end subroutine test_contiguous
|
|
|
| Back to top |
|
 |
JohnCampbell
Joined: 16 Feb 2006 Posts: 2629 Location: Sydney
|
Posted: Wed Oct 01, 2008 3:35 am Post subject: |
|
|
Paul,
I took the memory test subroutine and placed it in the large program I am wanting to use for extended memory.
I ran it at the start for a number of different working array sizes, with and without /3gb switch in slink.
1) without the 3gb in slink, only 2gb of memory is accessible.
2) with 300mb working array, i get a memory usage of :
first 371 mg is taken by program ( 300mb + 71mb)
at 1429mb, there is a 24.6mb gap
at 1486mb, a 3.5mb gap
at 1874mb, a 46.1mb gap
at 1984mb, a 63.9mb gap
3) with 1000mb working, a similar set of gaps
4) with 1600mb working array, i get a memory usage of :
first 1664 mg is taken by program ( 1600mb + 64mb)
gaps at 1429mb and 1486mb have been overwritten, ie omitted
at 1889mb, 46.1mb gap has been reduced to 30.8mb
at 1984mb, a 63.9mb gap
5) with 1750mb, similar (.map version)
ie, the gaps have been removed and do not appear to have been shifted
I did not run the program past the memory test.
There appears to be 3 parts of memory reserved for a small program, but only 2 for a larger program.
If the program encroaches on the 2 beyond 1889mb, then it becomes an illegal .exe
What are these 3 parts of memory being used for ?
Can they be relocated, perhaps to 2900mb or possibly to 64mb, and place the .bss section after them ?
I am attaching to an email the memory availability dump I generated from the memory scanning subroutine for these 5 tests and the last .map file for the program.
I did not run the program.
I have not yet tested the earlier real*8 array test to see if the memory allocated is useable.
Does this make any sense ?
Regards
John |
|
| Back to top |
|
 |
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8320 Location: Salford, UK
|
Posted: Mon Oct 06, 2008 11:55 am Post subject: |
|
|
Ian
I have not managed to find your sample code.
Can you send it again please to my hotmail account.
Paul |
|
| Back to top |
|
 |
JohnCampbell
Joined: 16 Feb 2006 Posts: 2629 Location: Sydney
|
Posted: Mon Oct 06, 2008 10:10 pm Post subject: |
|
|
Paul,
It appears that the attachments may have been deleted, as they contained .exe files. I will send it again, without the .exe.
I have included all the recent test programs.
Please let me know if the attachments are not there this time. Otherwise I will have to use my home email account !
John |
|
| Back to top |
|
 |
JohnCampbell
Joined: 16 Feb 2006 Posts: 2629 Location: Sydney
|
Posted: Wed Oct 08, 2008 5:08 am Post subject: |
|
|
Paul,
I have done a review of the large program I am wanting to run in 3gb of memory. The following is an approximate breakdown of the memory usage in the .map file:-
0.64mb .text - which is my code
0.12mb .data - which is salflibc/kernel32
0.69mb .salfdbg - presumably due to link map and /debug compilation
1.93mb .bss - my common excluding the big array
The total memory usage is 3.44 mb, excluding the big array
In summary, the memory usage, excluding the big array would be 0.1% of memory.
To use anything significantly above 2gb, the big array must be 99.9% of this. Either I must be able to have a single array bigger than 2gb or I have a major rewrite to use 2 big arrays or "chunks" in my algorithm.
The example problem I have been targeting to use for this /3gb approach requires an array of about 2.4gb in size. Will this be a possibility ?
Are any other forum users interested in this /3gb facility ?
Paul, thanks again for your assistance with this.
John |
|
| Back to top |
|
 |
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8320 Location: Salford, UK
|
Posted: Wed Oct 08, 2008 8:17 am Post subject: |
|
|
John
My understanding is that you cannot have a single array of more than 2GB.
Apart from rewriting your code, the only possible way forward would be to try running your program under WOW on a 64 bit machine and operating system. I don't know if anyone has tried this but you may be able to get 4GB this way. Alternatively you would have to switch to a 64 bit compiler, machine and operating system.
Paul |
|
| Back to top |
|
 |
DanRRight
Joined: 10 Mar 2008 Posts: 2959 Location: South Pole, Antarctica
|
Posted: Sat Oct 11, 2008 5:52 pm Post subject: Re: |
|
|
| PaulLaidler wrote: |
try running your program under WOW |
World of Warcraft?
For me 32bit is dead 15 years ago when I painfully hit its 1.6GB limit. Great that 32bit is finally dead starting with this fall shopping season. No single laptop in Best Buy or Frys right now is selling with 32bit XP (only one is the pocket EEE laptop), all are with 64bit Vista running 3-4 GB RAM.
For $99 total you can upgrade your desktop PC motherboard and 64bit processor, for $49 you'll get 4GB RAM (this month prices in Frys). You can get 64bit OEM Vista for cheap or use 64bit XP. The only what lagging are 64bit compilers. What is general obstacle to rewrite compiler for 64bit OS?
| JohnCampbell wrote: |
Are any other forum users interested in this /3gb facility ?
|
waste of time, I am sure you push a wrong button. With 64bit compiler you will get not factor 1.5-2 but many orders of magnitude more (well, of course Microsoft will restrict you just to not to forget who is the boss). That will totally change the way of thinking about your future algorithms |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|