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.
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.