Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Problems with alignment with allocatable arrays passed into subroutines

Fiona_R_
Beginner
819 Views

Hi, 

I'm having some problems getting allocatable arrays in my code to align correctly. The error message seems similar to that mentioned: https://software.intel.com/en-us/forums/topic/506377

My test code is as follows

program test_align
  implicit none
  integer :: cmax 
  integer, dimension(:, :), allocatable :: map
  cmax = 10
  
  allocate(map(-cmax:cmax,1:3))
  call mytest_sub(map,cmax)
  deallocate(map)

end program test_align


subroutine mytest_sub(map,cmax)
  implicit none
  integer, intent(in) :: cmax
  integer, intent(in) :: map(-cmax:cmax,1:3)
  integer, dimension(-cmax:cmax,1:3):: mapinternal
  integer, dimension(-cmax:cmax) :: i


!DIR$ ATTRIBUTES ALIGN: 64 :: i 
!DIR$ ATTRIBUTES ALIGN: 64 :: map
!DIR$ ATTRIBUTES ALIGN: 64 :: mapinternal
!DIR$ ASSUME_ALIGNED i:64

end subroutine mytest_sub

When I compile this I get the following error: 

ifort -O2 test_align.f90 -vec-report=6
test_align.f90(23): error #6406: Conflicting attributes or multiple declaration of name.   [MAP]
!DIR$ ATTRIBUTES ALIGN: 64 :: map
------------------------------^
compilation aborted for test_align.f90 (code 1)

Any ideas as to what the problem is here or indeed if there's any work around in the pipeline. Whilst I can clearly just take a copy of the map and make that local to the subroutine and align that array I'd like to avoid having to create lots of temporary arrays. 

Many thanks.

Fiona

 

0 Kudos
9 Replies
mecej4
Honored Contributor III
819 Views

Alignment specification on a formal argument of a subprogram is not logical. The argument map is not allocated memory in the subroutine, but by the caller (or higher up in the call chain). Whether the actual argument is aligned or not depends on how it was allocated in the subprogram where it was allocated (on the stack, the heap or the data segment).

Your directive, in effect, is asking to change the alignment on the fly. If this were actually done, the result would be havoc in the callers, since they would not be aware of the re-alignment.

Move the alignment directive to the main program in your example, and all will be well.

0 Kudos
TimP
Honored Contributor III
819 Views

I suppose attributes align belongs in the procedure where it can take effect on initial allocation, while assume_aligned is your assertion that you have taken care of alignment elsewhere.  The scope of these directives is local to a procedure, although interprocedural optimization may make assume_aligned redundant.

0 Kudos
Fiona_R_
Beginner
819 Views

Ah, many thanks Mecej4 and Tim.  Moving the align directive for map into the main program works for my test case.  It is slightly more complicated in the code I'm actually working with as pointers are involved! 

I assume if my map array is a pointer that I will then need to align the variable that map actually points to? rather than map itself? 

0 Kudos
TimP
Honored Contributor III
819 Views

Fiona R. wrote:

I assume if my map array is a pointer that I will then need to align the variable that map actually points to? rather than map itself? 

Yes, it's a similar situation to what mecej4 discussed; setting a pointer won't affect the alignment of a target.

0 Kudos
jimdempseyatthecove
Honored Contributor III
819 Views

Tim or Steve correct me if I am wrong:

There (currently) is no attribute you can apply to a pointer to enforce a runtime check that all => assignments point to aligned and contiguous data. One can make a function to assert this.

For example, you can make a user defined type that contains a pointer to an array of type of your choice. The user defined type could then have a contained procedure that receives an array or slice of array, and then asserts that the data is aligned and has stride of 1. Then on the called subroutine you pass it this type as opposed to the array or pointer to array.

On the other hand, you could place the assert inside your subroutine, and when not aligned, either a) call a different alignment agnostic routine or b) stop the program with an appropriate error message.

Jim Dempsey

0 Kudos
FortranFan
Honored Contributor III
819 Views

jimdempseyatthecove wrote:

...

There (currently) is no attribute you can apply to a pointer to enforce a runtime check that all => assignments point to aligned and contiguous data. One can make a function to assert this.

...

Look into CONTIGUOUS attribute introduced as part of Fortran 2008.  Also, see some discussion here https://software.intel.com/en-us/forums/topic/508693

 

0 Kudos
Steven_L_Intel1
Employee
819 Views

We don't support ATTRIBUTES ALIGN on dummy arguments. There is an open feature request for this, ID DPD200148387. You could have a local allocatable with ALIGN, do the allocation and then call MOVE_ALLOC to move the allocation to the dummy.

0 Kudos
Fiona_R_
Beginner
819 Views

Steve Lionel (Intel) wrote:

We don't support ATTRIBUTES ALIGN on dummy arguments. There is an open feature request for this, ID DPD200148387. You could have a local allocatable with ALIGN, do the allocation and then call MOVE_ALLOC to move the allocation to the dummy.

Many thanks Steve and everyone else. 

I think the local copy, ALIGN and MOVE_ALLOC could be my only option as I'm dealing with derived data types and pointers. I have a sneaky feeling that the overheads in taking the local copy etc may well outweigh any benefit I get from having the data aligned but it's certainly worth a go.  

0 Kudos
Steven_L_Intel1
Employee
819 Views

I agree that if you need to copy the data, that's bad, but I was not suggesting that. In your example, you need ATTRIBUTES ALIGNED on map in the caller where it is allocated, and on any local array variables in the subroutine such as i and mapinternal.

0 Kudos
Reply