4

I'm attempting to understand how to pass a slice of a multidimensional co-array to a function. I would like to use a function like this:

    function get_int_vec(vec_int_2get, rank) result(ret_val)
      implicit none
      integer,  dimension(:), codimension[*], intent(in) :: vec_int_2get
      integer, intent(in) :: rank
      integer, allocatable, dimension(:) :: ret_val 

      ret_val = vec_int_2get(:)[rank]

    end function ! get_int_vec

It works fine to get an entire array. But when passing a slice of a coarray, like:

    vec_getA(:) = get_int_vec(matrix_A(n, :), rank)

where matrix_A is declared as

    integer, dimension(:, :), codimension[:],  allocatable :: matrix_A

and properly allocated, I always get the first column of matrix_A instead of the n-th.

The gfortran passing conventions say:

" with -fcoarray=lib [...] the token and the offset belonging to nonallocatable coarrays dummy arguments are passed as hidden argument along the character length hidden arguments. The token is an opaque pointer identifying the coarray and the offset is a passed-by-value integer of kind C_PTRDIFF_T, denoting the byte offset between the base address of the coarray and the passed scalar or first element of the passed array."

So I was expecting the function to work fine also with matrix slices, since the offset from the beginning of the matrix should be passed along to the function.

There is something am I doing wrong?

If can be of some interest: I am compiling with Intel Parallel Studio XE 2018 cluster edition, and not the OpenCoarrays version of coarrays.

Sparonuz
  • 145
  • 7
  • 2
    If you wonder why you did not get any answer or comment: it is really simple, you use irrelevant tags or tags that no one subscribes to. Tags are extremely imporant on Stack Overflow. Use tag [tag:fortran] for all Fortran questions. – Vladimir F Героям слава Jul 11 '18 at 06:14
  • Sorry, for the tags. I am using Intel version of Coarrays, and not openCoarrays, as I said I'm using the Intel compiler. – Sparonuz Jul 11 '18 at 08:01
  • OK, I can now see where the confusion comes from. These conventions are NOT Fortran standard conventions, they are gfortran compiler-specific conventions and should not actually matter too much when you stay inside standard Fortran. – Vladimir F Героям слава Jul 11 '18 at 11:47
  • You're totally right, I edited away that part. Thank you for your comments, but I'm wondering now if the quote is relevant at all, since, as you said, it's a compiler-specific convention, and I'm not even using this compiler. – Sparonuz Jul 11 '18 at 12:39
  • I think it is not really relevant. What is relevant is the Fortran standard document. – Vladimir F Героям слава Jul 11 '18 at 12:42
  • You should probably seek support from Intel with this problem. – francescalus Jul 11 '18 at 15:18
  • My implementation of your question using Intel ifort 18 Windows did produce this error. As @francescalus said, you may want to post this on Intel forum for an answer from Intel ifort team. please keep in mind to always post a minimal working example of your question. It makes a big difference. – Scientist Jul 11 '18 at 23:10
  • Thank you very much for you help. That was my fear and, I was actually trying to run the code with openCoarrays, but you were faster. That was my fear, since I'm not eligible for Intel support, since I just have access to their compilers on a cluster. I'll try anyway! Thank you all. – Sparonuz Jul 12 '18 at 08:00
  • @Sparonuz I have submitted a ticket to Intel ifort team regarding this bug in their compiler. – Scientist Jul 14 '18 at 19:25
  • @King Thank you very much! I tried to post a question on their forum, but I got no answer yet. – Sparonuz Jul 16 '18 at 07:34
  • @Sparonuz I wanted to bring to your attention if you have not seen it already, an amazingly cool work that has been done by the Sourcery Institute to make Coarray Fortran available in the cloud via Jupyter notebooks. That means, if you have Parallel Coarray Fortran ideas, you can directly test them quickly and directly in a Jupyter notebook without a local installation of a modern Fortran compiler. To access the Jupyter kernel, click on "Try" on the Kernel's Github page here: https://github.com/sourceryinstitute/jupyter-CAF-kernel – Scientist Aug 18 '18 at 01:15

1 Answers1

2

This seems to be a bug in Intel ifort 2018. The syntax of your code appears to conform with Fortran 2008 standard (here). The same code compiled with OpenCoarrays and GFortran yields the expected results. Here is a (not so minimal but) working implementation of your question:

module coarrayFunc
    implicit none
contains
    function get_int_vec(vec_int_2get, rank) result(ret_val)
        implicit none
        integer,  dimension(:), codimension[*], intent(in) :: vec_int_2get
        integer, intent(in) :: rank
        integer :: ret_val(3)
        !integer :: ret_val(size(vec_int_2get)) ! using this results in internal compiler error when compiled with ifort.
        !integer, allocatable :: ret_val(:) ! both ifort and OpenCoarrays (GFortran) compile with this declaration, however both ifort give wrong results.
        ret_val = vec_int_2get(:)[rank]
    end function ! get_int_vec
end module coarrayFunc

program testNoncontiguousCoarray
    use coarrayFunc
    implicit none
    integer, allocatable    :: matrix_A(:,:)[:], dummy(:)
    integer                 :: rank, n, i, j, image
    integer, parameter      :: ilower = 1, iupper = 5
    integer, parameter      :: jlower = 1, jupper = 3

    allocate( matrix_A(ilower:iupper,jlower:jupper)[*] )

    do i = ilower, iupper
        do j = jlower, jupper
            matrix_A(i,j) = this_image()*100 + i*10 + j
        end do
    end do

    ! print matrix_A on each image
    sync all
    if (this_image()==1) then
        do image = 1, num_images()
            write(*,"(*(g0))") "matrix_A on image ", image, ":"
            do i = ilower, iupper
                write(*,"(*(g8.1))") matrix_A(i,:)[image]
            end do
            write(*,"(*(g0))")
        end do
        sync images(*)
    else
        sync images(1)
    end if
    sync all

    n = iupper
    rank = this_image()
    !rank = num_images()

    sync all
    if (this_image()==1) then
        write(*,"(*(g0))")
        write(*,"(*(g0))") "On all images: "
        write(*,"(*(g0))") "n = ", n
        write(*,"(*(g0))")
    end if
    sync all

    if (this_image()==1) then
        write(*,"(*(g0,' '))") "On Image ", this_image(), ": matrix_A( n =", n, ", : )[",rank,"] = ", matrix_A(n,:)[rank]
        dummy = get_int_vec(matrix_A(n,:), rank)
        write(*,"(*(g0,' '))") "On Image ", this_image(), ": get_int_vec( matrix_A( n =", n, ", : ), rank =", rank, ") = " &
                               , dummy
    else
        sync images (this_image()-1)
        write(*,"(*(g0,' '))") "On Image ", this_image(), ": matrix_A( n =", n, ", : )[",rank,"] = ", matrix_A(n,:)[rank]
        dummy = get_int_vec(matrix_A(n,:), rank)
        write(*,"(*(g0,' '))") "On Image ", this_image(), ": get_int_vec( matrix_A( n =", n, ", : ), rank =", rank, ") = " &
                               , dummy
    end if
    call sleep(1)
    if (this_image()<num_images()) sync images (this_image()+1)

end program testNoncontiguousCoarray

Compiling and running this code with OpenCoarrays yields:

matrix_A on image 1:
    111     112     113
    121     122     123
    131     132     133
    141     142     143
    151     152     153

matrix_A on image 2:
    211     212     213
    221     222     223
    231     232     233
    241     242     243
    251     252     253

matrix_A on image 3:
    311     312     313
    321     322     323
    331     332     333
    341     342     343
    351     352     353

matrix_A on image 4:
    411     412     413
    421     422     423
    431     432     433
    441     442     443
    451     452     453


On all images: 
n = 5

On Image  1 : matrix_A( n = 5 , : )[ 1 ] =  151 152 153 
On Image  1 : get_int_vec( matrix_A( n = 5 , : ), rank = 1 ) =  151 152 153 
On Image  2 : matrix_A( n = 5 , : )[ 2 ] =  251 252 253 
On Image  2 : get_int_vec( matrix_A( n = 5 , : ), rank = 2 ) =  251 252 253 
On Image  3 : matrix_A( n = 5 , : )[ 3 ] =  351 352 353 
On Image  3 : get_int_vec( matrix_A( n = 5 , : ), rank = 3 ) =  351 352 353 
On Image  4 : matrix_A( n = 5 , : )[ 4 ] =  451 452 453 
On Image  4 : get_int_vec( matrix_A( n = 5 , : ), rank = 4 ) =  451 452 453

which outputs the result one would expect to get. Note that I have tweaked your original function so that the function's result would be an automatic array instead of allocatable (This appears to be yet another bug in OpenCoarrays, that is, an allocatable output return wrong results). Running the same code using ifort 2018 Windows would reproduce the error that you observe in your own implementation:

>set FOR_COARRAY_NUM_IMAGES=4

>ifort /Qcoarray=shared testNoncontiguousCoarray.f90 -o run.exe
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 18.0.2.185 Build 20180210
Copyright (C) 1985-2018 Intel Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 14.13.26129.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:run.exe
-subsystem:console
testNoncontiguousCoarray.obj

>run.exe
matrix_A on image 1:
     111     112     113
     121     122     123
     131     132     133
     141     142     143
     151     152     153

matrix_A on image 2:
     211     212     213
     221     222     223
     231     232     233
     241     242     243
     251     252     253

matrix_A on image 3:
     311     312     313
     321     322     323
     331     332     333
     341     342     343
     351     352     353

matrix_A on image 4:
     411     412     413
     421     422     423
     431     432     433
     441     442     443
     451     452     453


On all images:
n = 5

On Image  1 : matrix_A( n = 5 , : )[ 1 ] =  151 152 153
On Image  1 : get_int_vec( matrix_A( n = 5 , : ), rank = 1 ) =  111 112 113
On Image  2 : matrix_A( n = 5 , : )[ 2 ] =  251 252 253
On Image  2 : get_int_vec( matrix_A( n = 5 , : ), rank = 2 ) =  211 212 213
On Image  3 : matrix_A( n = 5 , : )[ 3 ] =  351 352 353
On Image  3 : get_int_vec( matrix_A( n = 5 , : ), rank = 3 ) =  311 312 313
On Image  4 : matrix_A( n = 5 , : )[ 4 ] =  451 452 453
On Image  4 : get_int_vec( matrix_A( n = 5 , : ), rank = 4 ) =  411 412 413

As mentioned in the comments to your question, consider writing a minimal working example of code that reproduces the error you get, and submit a ticket to Intel's ifort compiler team, for a potential resolution.

Scientist
  • 1,767
  • 2
  • 12
  • 20