- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In fortran, how can I ensure allocated arrays are 16 byte aligned as oposed to 8 byte aligned?
Kind regards,
Pete
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This guy here claims that !DEC$ATTRIBUTES ALIGN appears to work even for allocatables, but I strongly doubt it. I see no magic whereby that could be achieved: as far as I know, ALLOCATE ultimately calls either malloc from underlying C runtime library or some XXXAlloc API, but plain malloc does not guarantee the alignment (except possibly for fairly large sizes).
The "standard" C way to do that is to allocate 16 bytes more than you need, then align the returned value from malloc, but you have to keep the original value as well, so that you can free() it later. I don't see a way to do it in Fortran though. I wrote a routine which "overloads" the standard RTL for_alloc_allocatable_ and can mock with the array descriptor. Thus, I can probably post a solution that will guarantee that you'll get a 16-byte-aligned array back from ALLOCATE -- but not guarantee that you'll be able to deallocate it . Unless someone else comes up with an Idea.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have tried:
real(KIND=8), pointer, public :: aDouble(:) => null()
!DEC$ ATTRIBUTES ALIGN: 16 :: aDouble
Unfortunately this causes:
fortcom: Fatal: There has been an internal compiler error (C0000005).I therefore assumed it was not possible to use this !DEC$ with dynamic arrays.
Instead I have done something like this:
real(KIND=8), pointer, public :: aDouble(:) => null()
integer :: aDoubleFreeAddress, i
aDouble = malloc( ((nmat*nmat*8)+16) )
do i = 0, 15
if ( modulo( (aDoubleFreeAddress+i), 16 ) .EQ. 0 ) then
aDouble = (aDoubleFreeAddress+i)
exit
end if
end do
...more code...
call free(aDoubleFreeAddress)
aDouble => null()
I am now stumped with fortran pointers as the debugger is showing aDouble still to be an Undefined pointer/array.
Pointers in C always seemed to make sense :<
Is it possible to do what I am trying to do in the above code? ( get aDouble to point to (aDoubleFreeAddress+i) )
Kind regards,
Pete
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
MADsblionel:
Why do you doubt it, Jugoslav? It's supposed to work. The Fortran ALLOCATE routine requests enough extra and returns an aligned address. It even works if the variable is stack-allocated.
Well, for the start, Hager said, quote, that "Although the compiler docs say at some point that this doesn't work for allocatables...". I now checked the docs myself and they don't say so; at least not anymore. However, I'm very curious about implementation then:
1) How big is the "enough extra"??? I'm just playing with it and I'm getting unaligned addresses from for_allocate for 344144; 1488; 1920 and 95600 requested bytes (among other figures). (Note that one array is 350 kB!)
2) If that's not the technique, I suppose malloc-then-align-the-base is an easier option. However, where does one keep both the original and the aligned address? It might be possible using both BASE and OFFSET fields in the array descriptor, but I'm not sure how.
3) Or does it do something entirely different, like calling a different run-time routine which calls something else in C RTL?
I'll do some reverse-engineering, but I'm really eager to learn how it's implemented...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
1) You should declare aDouble to be an ALLOCATABLE rather than pointer; if only for practical reasons.
2) You have just discovered a compiler bug: whatever you have done, "internal compiler error (C0000005)" is always one. Which Ifort version are you using? If it's relatively new, Intel folks would certainly love to have a sample code which produces the error.
3) OK, Steve, I verified that it does work -- it's seems to be the 3rd argument to for_alloc_allocatable/for_allocate (the one whose semantics I've never got to reverse-engineer) that regulates the behavior, right? For an appropriate bit set, something like alligned_malloc() is called from Fortran RTL, otherwise the plain malloc() one.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm using version 10.1.021
The output looks like this:
1>------ Build started: Project: ISISf_IVF_IVF10v3, Configuration: Debug Win32 ------
1>Compiling with Intel Fortran Compiler 10.1.021 [IA-32]...
1>matrixdata.f90
1>PSolve.F90
1>fortcom: Fatal: There has been an internal compiler error (C0000005).
1>compilation aborted for C:devisis-fPSolve.F90 (code 1)
1>
1>Build log written to "file://C:devisis-fCompaqVFISISCVFISISf_CVF2DebugBuildLog.htm"
1>ISISf_IVF_IVF10v3 - 1 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 3 up-to-date, 0 skipped ==========
I will try and write a sample program to replicate this bug. Unfortunately I don't think I will be able to send in the bug "in situ" as the original source code is huge and i'm not sure about confidentiality issues.
Let me see if I can make a smaller version to replicate it.
Regards,
Pete
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
module m_align
integer, allocatable:: i1(:)
!DEC$ATTRIBUTES ALIGN:16 :: i1
end module m_align
program align
use m_align
allocate(i1(1))
end program align
1>Compiling with Intel Fortran Compiler 10.1.021 [IA-32]...
1>Align.f90
1>fortcom: Fatal: There has been an internal compiler error (C0000005).
1>compilation aborted for D:UsersDujaCodeMy SamplesAlignAlign.f90 (code 1)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
MADsblionel:
So you are seeing this directive doing the alignment for local ALLOCATABLE arrays?
Yes.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The alignment of A4 is 4
The alignment of A8 is 32
The alignment of A16 is 16
The alignment of A32 is 1024
The alignment of A64 is 128
The alignment of A128 is 256
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In terms of a workaround for the moment, I have done something like this:
real(KIND=8), pointer, public :: aDouble(:) => null()
real(KIND=8), allocatable, target :: aDoublePriv(:)
!DEC$ ATTRIBUTES ALIGN: 16 :: aDoublePriv
In the module (locally) i then have:
allocate( aDoublePriv(nmat*nmat), stat = istat )
call check_allocate_status(istat)
aDouble => aDoublePriv
parts of my program in other modules then access the aligned array through aDouble as normal
It's a bit of a bodge but it seems to be working for the moment.
Regards,
Pete

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page