Allocatable array not reconized as contiguous

Hi all,

I meet a problem whith nvfortran from nvhpc/22.3. In a module, I define a type with an allocatable 2D array attribute. It is not allowed in fortran to specify contiguous for this array, it is implicit as it is allocatable. In the main program, I have a pointer variable on this type and a pointer variable on a 1D array to change the shape of the attribute to 1D. This does not compile with nvfortran as the contiguity character seams lost:

NVFORTRAN-S-0155-Illegal POINTER assignment - pointer target must be simply contiguous (main.f90: 13)

But it works with gfortran and ifort. A small test case to reproduce is provided below.

Am I wrong in my fortran knowledge or is it nfvortran which is wrong ?

NVIDIA-CONTIGUOUS.tgz (732 Bytes)

Hi Patrick,

I’m not really sure why the other compilers are accepting your PROGRAM, because the syntax doesn’t really make sense to me. The following is what I would expect:

program test_contiguous
   use array_m
   implicit none

   type(array_t), target :: T
   integer, parameter:: dim=10
   real, pointer, dimension(:,:) :: ptr

   call init_array(dim, dim, T)
   ptr =>T%val
   ptr=0
   call del_array(T)
end program test_contiguous

Your T needs to be target rather than pointer, otherwise init_array is operating on an unassociated pointer. The pointer declaration should be dimension(:,:), as it needs to match the rank of the data target. If you are going to use bounds on the left-hand side of the pointer assignment, they need to be of the same rank as the data target, but here, you don’t need them. Once you switch to this main, the program is correctly compiled on all of the compilers.

And, just as an aside, there really isn’t a need to explicitly store dim1 and dim2 in your type: you can always retrieve that from the array itself (or an associated pointer) with the SHAPE intrinsic.

Hope this helps…
Paul

All of that being said, I think there is still a problem with nvfortran. If you put replace the pointer assignment above with:

ptr(1:dim, 1:dim) => T%val

(a trivial bounds-remapping-list), then nvfortran 22.3 complains:

NVFORTRAN-S-0155-Illegal POINTER assignment - pointer target must be simply contiguous (main.f90: 10)

which it is, as it is an object name that is not a pointer, an assumed shape, or an assumed size.

Paul

1 Like

Hi Paul,
Thanks too look into my problem,

You’re right, my small code is wrong, T must not be a pointer in the main (I had not run the executable). This is not the real code, just some lines trying to isolate the problem I have with a very large application. The real types are significantly more complexes and the pointer is required as in the real code it is a loop and T is an element of a chained list (each element containing allocatables arrays). All this is in a subroutine and T is one of the arguments. May be I simplify too much.
Fortran allows to declare ptr as a one dimension shape, to switch from a 2D T%val(n,n) array to a ptr(n²) vector array (the case I try to illustrate). This requires only that the array T%val(:,:) is contiguous in memory. If in the module “array” the attribute “val” of the array_t type is a pointer with contiguous attribute, the compiler agree. But if it is an allocatable (which is contiguous) it does not.
I think the original syntax is correct: ptr(1:allpoints)=>T%val in this situation.

1 Like

Gotcha. However, my understanding is that Fortran does not let you change rank in a pointer assignment. From section 10.2.2.2 of the F2018 draft:

C1017 (R1033) If bounds-spec-list is specified, the number of bounds-specs shall equal the rank of data-pointer- object.
C1018 (R1033) If bounds-remapping-list is specified, the number of bounds-remappings shall equal the rank of data-pointer-object .
C1019 (R1033) If bounds-remapping-list is not specified, the ranks of data-pointer-object and data-target shall be the same.

I think that all of the compilers are mis-diagnosing that. But nvfortran is also incorrect about the simply contiguous.

Hi Paul,
I’m not familiar with reading fortran specifications but reading Fortran 2008/2018 specifications from https://www.nag.com/market/training/fortran-workshop/f2018_standard.pdf

Rank remapping can be applied to CONTIGUOUS arrays, for example:
REAL, CONTIGUOUS, POINTER :: A(:)
REAL, CONTIGUOUS, TARGET :: B(:,:) ! Dummy argument
A(1:SIZE(B)) => B
! Linear view of a rank-2 array
and it is what we are doing in the code, but with modules

Even if this syntax doesn’t work :-(

However testing this on a small peace of code:

program short
   implicit none
   REAL, CONTIGUOUS, POINTER :: A(:)
   REAL, ALLOCATABLE, TARGET :: B(:,:) ! Dummy argument
   integer ::i,j
   integer, parameter :: n=10

   allocate (B(n,n))
   do  i=1,n
       do j=1, n
          B(i,j)=i+j
       enddo
   enddo
   A(1:SIZE(B)) => B
   print*,"shape(B)= ",shape(B)," shape(A)= ",shape(A)
   print*,"Sum(B)= ",sum(B)," Sum(A)= ",sum(A)
! Linear view of a rank-2 array
end program short

it works.
Could it be related to the module use ? Or the use of a user defined type as the “continuous” attribute is not allowed for a type element ?

I’m sorry, you’re absolutely correct. The number of bounds have to match the rank of the pointer object itself, not the target. Thanks for pointing out that example!

I would guess that it the error is that nvfortran is not properly retrieving the correct information from the TYPE, rather than it being a module, but that’s up to the nvidia engineers to figure out!

Sorry again for my mistake.

Paul

As my penance for being an idiot, here is a minimal reproducer:

program test
  type container
     integer, allocatable :: data(:,:)
  end type container

  type(container), target :: T
  integer, pointer, dimension(:) :: ptr

  allocate(T%data(10,10))
  ptr(1:100) => T%data
  ptr = 0
end program test

Thanks Paul for this more synthetic test case. May be this remapping is not frequently used by nvfortran users.
Is there a way to record an issue about this ?
On a previous problem Mat Colgrove did it for me and I do not know how to do this (and if it is allowed)

Hi Paul,
There is a workaround to this bug that can help people stuck with it. Just using an intermediate pointer, contiguous and with same rank the target has, then switching to one dimensional.

program test
type container
integer, allocatable :: data(:,:)
end type container

type(container), target :: T
integer, pointer, dimension(:) :: ptr
integer, pointer, contiguous, dimension(:,:) :: temp

allocate(T%data(10,10))

temp => T%data
ptr(1:100) => temp

ptr = 0
end program test

@MatColgrove It looks like Patrick found a real issue… can you do your magic here?

Thanks,
Paul

Thanks Paul for stepping in and Patrick for the original issue.

I’m double checking with engineering but think that this is a F2008 or F2018 feature not available in nvfortran.

We’ve deferred much of this support until the f18 flang project we’re developing with the community is complete. We’ll then switch nvfortran to use the f18 front-end. The example code compiles correctly in the current flang: llvm-project/flang at main · llvm/llvm-project · GitHub

-Mat

I was wrong, it’s a bug not a feature issue. Reported as TPR #31638.

The suggested work around is to use “ptr(1:100) => T%data(:,:)”

On a previous problem Mat Colgrove did it for me and I do not know how to do this (and if it is allowed)

I missed this. You can submit bug reports yourself through the NVBUG portal. The TPR system is carry over from our PGI days, but our team still likes it given the 30+ years of history and ease of use. Though, we use the NVBUG system as well.

To report a NVBUG, go to https://developer.nvidia.com/ and select your account page (the person symbol on the upper right). From there, look for the “My Bugs” link to take you to your bug report page. Then select the “submit a new bug” button.

Note I don’t mind writing up bug reports directly into the TPR system. Which ever you prefer is fine.

-Mat

2 Likes

Hi Mat,
Yes this is a F2008 feature in my mind and the code is moving to Fortran 2008 for several months now.
As we are working on moving this large code to GPU at the same time, we are also checking for portability with various compilers, for cpu and for gpu using OpenMP5 offloading.
For this test-case, Intel, Gnu and Cray are working. Aomp and Nvidia are not. Bad news for our GPU offloading work, but the workaround solves the issue with few modifications. So good news too!

Any idea about the roadmap for the availability of the f18 front-end for nvfortran ?
Thanks
Patrick

Nope, sorry. They are working on getting f18 production ready, but nothing specific on when that will be.

Hi Partrick, Paul,

TPR #31638 has been fixed in our 22.5 release.

% cat con.f90
program test
  type container
     integer, allocatable :: data(:,:)
  end type container

  type(container), target :: T
  integer, pointer, dimension(:) :: ptr

  allocate(T%data(10,10))
  ptr(1:100) => T%data
  ptr = 0
end program test
% nvfortran -V22.3 con.f90
NVFORTRAN-S-0155-Illegal POINTER assignment - pointer target must be simply contiguous (con.f90: 10)
  0 inform,   0 warnings,   1 severes, 0 fatal for test
% nvfortran -V22.5 con.f90
%

-Mat

Hi Mat

Thanks for this information! It is a good news when bug are solved and new functionalities added.

I was testing also memory allocation in target subroutines. Working for allocatable but not for pointers with nvfortran 22.5-0 :
NVFORTRAN-S-1058-Call to PGI runtime function not supported - pgf90_ptrcp (ex.f90: 8)

Is this something we must not do on a GPU or just futur development of the compiler ?

Patrick

Hi Patrick,

In general, it’s not advisable to perform allocation (including using automatics which are implicitly allocated) on the device. Allocation is serialized so can severely hurt performance, plus the default heap size is quite small so it easy to encounter heap overflows.

For the pointer copy (ptrcp) runtime call in particular, I’m not sure if it’s deliberately not be ported to the GPU, or if we just haven’t had a compelling use case to port it. If you do indeed need to use this, I can submit an RFE and see what engineering can do. A reproducing example would be appreciated.

-Mat

Thanks Mat for this precision. The data structure of the code I’m working on is based on chained lists. I was thinking managing a copy of the data structure on the GPU (as all data management is centralised in some fortran modules) and try to move most of the execution on the GPU. It looks like it is not the best approach and may be small kernels will be more appropriate.
Patrick

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.