- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Greetings!
I am running the following code on a 32-bit Win7 machine with /3GB option enabled. The code is compiled with option /largeaddressaware.
integer(8) :: locarr ! allocation is successful and allocerr is zero; arr uses about 30MB of memory allocate (arr(1:length), stat = allocerr) ! loc returns negative integer locarr = loc(arr)
The documentation says that the result type of loc is "INTEGER(4) on IA-32 architecture; INTEGER(8) on Intel® 64 architecture". I can see that the array is allocated beyond the 2GB barrier. Therefore, I suspect that there is an integer overflow because the starting address of 'arr' does not fit into integer(4). Am I correct? I think I am missing something.
I would appreciate any help / comments. The compiler version is
Version 12.0.3.175 Build 20110309
-Franz
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello
Memory addresses are unsigned values from 0 to 232-1 in a 32bits architecture
Integer values in fortran are signed. So it is normal that the loc function could return a value (>=231) that is considered by fortran as negative. So when you assign the return value to an integer(8) variable it is always considered as negative.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@gvautier: thanks for your comments.
So cray (integer) pointers will just not work if "allocate" allocates memory above the 2 GB barrier on win32? I tried to increase the size of the cray pointers to integer(8) on win32, but got the following error:
Error #7226: An integer pointer variable has been explicitly given a data type that is not the integer type and kind for an address on the current platform.
Unfortunately, I cannot move away from using cray pointers easily and, therefore, I am looking for ways to work around this.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
There's no evidence here that Cray pointers won't work. Normally, you would not be making a 64-bit signed copy of a 32-bit pointer and caring about its sign. If you have a reason for making a 64-bit copy, you could zero extend, if that helps.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
There is no issue with storing unsigned integers in signed integers provided that you do not perform math or relational operations that assume the numbers are properly ranged (sign bit 0). Such as:
if(CrayPointerA .LT. CrayPointerB) ...
ShortPointer = CrayPointer / 4
Instead use
if(SHIFT(CrayPointerA, 2) .LT. SHIFT(CrayPointerB, 2)) ...
ShortPointer =SHIFT(CrayPointer, 2)
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello
I think that plus or minus operations can be made safely.
multiply might work
but divide not because the result for dividing a negative number will be a negative number
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Multiply would produce incorrect result if multiplicand were .gt. 1.
The if(SHIFT(CrayPointerA, 1) .LT. SHIFT(CrayPointerB, 1)) ... is the most effective way to compare two pointers and get the correct result....
I take that back... The above is true provided that the pointers are to objects that are at least 2 bytes long. For 1 byte protection
if( IAND(INT8(CrayPointerA), Z'00000000FFFFFFFF') .LT. IAND(INT8(CrayPointerB), Z'00000000FFFFFFFF') ) then ...
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Fortunately, operations on addresses are mainly additions or subtractions.
If you want to store interg(4) pointers in integer(8) then
CrayPointer8=IAND(INT8(CrayPointer4), Z'00000000FFFFFFFF')
is the best way.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Life is just too short to count all those F's. The ifort extension:
CrayPointer8 = ZEXT(CrayPointer4,KIND(CrayPointer8))
would be my choice; don't know why the standards committee hasn't co-opted it. The standard syntax is:
CrayPointer8 = IAND(INT(CrayPointer4,KIND(CrayPointer8)),MASKR(BIT_SIZE(CrayPointer4),KIND(CrayPointer8)))
which is just a little verbose.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You can use the standard intrinsic TRANSFER to obtain the value as Integer*8. I use the following function to return memory addresses on Win32 between 2gb to 4gb.
integer*8 function JLOC (mem) integer*4 mem integer*4 ii(2) integer*8 jj ! ii(1) = loc (mem) ii(2) = 0 jloc = transfer (ii,jj) end
The following program will report successfully on 64 bit OS systems that support /3gb using 32 bit compiler.
integer*8 JLOC, address external JLOC integer*4 ii, n, stat integer*4, allocatable, dimension(:,:) :: aa, bb, cc real*4 mb ! address = JLOC (ii) write (*,*) address, loc(ii) ! ! allocate 3 arrays of 800 mb n = nint ( sqrt ( (800.*1024.*1024.) / 4. ) ) write (*,*) 'Array dimension =',n ! allocate ( aa(n,n), stat=stat ) mb = real(Jloc(aa)) / 1024./1024. write (*,*) 'AA allocated : stat=',stat, JLOC(aa), loc(aa), mb ! allocate ( bb(n,n), stat=stat ) mb = real(Jloc(bb)) / 1024./1024. write (*,*) 'BB allocated : stat=',stat, JLOC(bb), loc(bb), mb ! allocate ( cc(n,n), stat=stat ) mb = real(Jloc(cc)) / 1024./1024. write (*,*) 'CC allocated : stat=',stat, JLOC(cc), loc(cc), mb ! end
![](/skins/images/3CECF0550DB8BF54496C114A1FF06FE9/responsive_peak/images/icon_anonymous_message.png)
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page