This is the mail archive of the
fortran@gcc.gnu.org
mailing list for the GNU Fortran project.
Coarray RFC and status
- From: Tobias Burnus <burnus at net-b dot de>
- To: gfortran <fortran at gcc dot gnu dot org>, Daniel Carrera <dcarrera at gmail dot com>
- Date: Mon, 09 May 2011 22:09:10 +0200
- Subject: Coarray RFC and status
Dear all,
below you find the near-term agenda for coarrays in gfortran.
First, some issues with storing *scalar* coarray variables has still to
be solved. For those, the middle end has to see scalars and also all
usage has to be as for scalars. At the same time, GFC_POINTER_TYPE_P has
to be set as GFC_TYPE_ARRAY_UBOUND is used to store the cobounds. The
first patch is at http://gcc.gnu.org/ml/fortran/2011-05/msg00067.html,
but that's not sufficient as it generates an array type for the ME -
thus, trans-types.c needs to modified (cf. attachment), but that in turn
causes failures as GFC_POINTER_TYPE_P somehow got lost. I think both
patches are correct, but insufficient ...
Secondly, for gfortran.dg/coarray/caf.exp, one needs to add support for
running the program with MPI. One probably needs to override
gfortran_load and work with getenv GCC_TEST_RUN_CAF_OPTIONS and
GCC_TEST_RUN_CAF_RUNCMD.
Thirdly, the real coarray support for which I want to loosely follow
Nick's draft, cf. http://gcc.gnu.org/ml/fortran/2010-04/msg00168.html.
(See also http://gcc.gnu.org/wiki/CoarrayLib for some function prototypes.)
The first step is registering and deregistering coarrays. The
registering of nonallocatable coarrays has to happen at startup. For
that we will use GCC's constructor attribute such that for
each procedure which contains a coarray, a nested procedure is
generated: For example, for
SUBROUTINE proc()
INTEGER, SAVE :: coarray[*]
the generated code should look somehow like the following (pseudo
-fdump-tree-original):
proc ()
{
static integer(kind=4) *coarray;
static void *token.1;
void __attribute__((constructor)) _caf_init (void)
{
coarray = _gfortran_caf_register (sizeof(integer(kind=4)), 0, &token);
}
Thus, all static scalar/array coarrays have to be turned into pointers
and get an associated "token" variable, which saved in the
TYPE_LANG_SPECIFIC node - along side the bounds of nondescriptor
variables (cf. type.h's lang_type).
The collective deregistration is performed when _gfortran_caf_finalize is
called - doing so via a deconstructor would be too late. That finalize
function is called at the end of the main program and for STOP.
As the front end does not call the library for each deregistration, the
library itself needs to keep track of the allocatations.
One question has to be solved: Where are errors handled? In the
generated front-end code or in the library? One could add in the front
end code as in:
coarray = _gfortran_caf_register (...)
if (coarray == NULL)
_gfortran_caf_error_stop_str ("Could not allocate coarray
'coarray'", 36);
Or one handles it in the library. Going for the library has the
advantage that the file size gets smaller (less code duplication) and
that the library should know better why the failure occured. On the
other hand, the front end knows file, line number and name of the
coarrays. However, I am inclined to leave the error handling to the library.
For improved diagnostics (-fcheck=...), I am thinking another version of
the registering function should be included, which could get passed more
information: file, line number, coarray variable name, bounds, cobounds.
For the default version, I think one can do with minimal information.
Thus, for registration, the work item would be:
- libcaf_single: Keep track of the allocations in order to free the
variables at the end
- Front end:
. Convert the static coarray variables into ((non)restricted) pointers
. Generate a token variable and save its decl in the lang-specific node.
. Create a constructor function and invoke it.
- libcaf_mpi: Similar to libcaf_single, but with all the issues for
parallel usage
For allocatable coarrays, the procedure is similar, except that the
registering is done via an explict ALLOCATE call and that one has a
deregistering via an (explicit/implicit) DEALLOCATE. It might make sense
to distinguish between allocatable and nonallocatable coarrays in the
registering call by passing a different type to the function (Nick's
proposal has 0 = normal coarray, 1 = lock and 2 = with lock component.)
For the front end, the main work is probably to fix all issues related
to turning static scalars/arrays into static pointer variables (and the
array or not array issue mention at the very top). The creation of the
nested constructor function is probably lengthy but relatively straight
forward.
For the library, the main work will presumably the implementation of the
event loop; while I have not thought about this part, Nick has. Thus, I
leave the writing of the scheme to him.
After all of the things above work, the fun part starts: Implementing
actual communication. My idea is to implement first a scalar pull; i.e.
obtaining data from a remote coarray for local use. Hopefully, it will
be relatively simple after all the other work has been done.
Next comes (chronologically unorderd): Support for coarray dummy
arguments, allocatable (array) coarrays, whole-array operations and
pushing data to remove coarrays. SYNC IMAGE support, LOCK and CRITICAL
support.
Finally, allocatable scalars, atomic, diagnostic, cleanup, possibly
adding more push/pull support optimized for special cases, adding a
helper process, ...
Do you have any comments or suggestions - or do you even offers to help
with one of those items?
Tobias
2011-05-07 Tobias Burnus <burnus@net-b.de>
PR fortran/18918
* trans-types.c (gfc_get_nodesc_array_type): Make sure that the
middle end sees scalar coarrays as scalar.
2011-05-07 Tobias Burnus <burnus@net-b.de>
PR fortran/18918
* gfortran.dg/coarray_21.f90: New.
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index 22a2c5b..6450f3f 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -1423,7 +1423,10 @@ gfc_get_nodesc_array_type (tree etype, gfc_array_spec * as, gfc_packed packed,
/* We don't use build_array_type because this does not include include
lang-specific information (i.e. the bounds of the array) when checking
for duplicates. */
- type = make_node (ARRAY_TYPE);
+ if (as->rank)
+ type = make_node (ARRAY_TYPE);
+ else
+ type = etype;
GFC_ARRAY_TYPE_P (type) = 1;
TYPE_LANG_SPECIFIC (type)
@@ -1537,6 +1540,9 @@ gfc_get_nodesc_array_type (tree etype, gfc_array_spec * as, gfc_packed packed,
build_qualified_type (GFC_TYPE_ARRAY_DATAPTR_TYPE (type),
TYPE_QUAL_RESTRICT);
+ if (as->rank == 0)
+ return type;
+
if (known_stride)
{
mpz_sub_ui (stride, stride, 1);
--- /dev/null 2011-05-06 19:43:06.071892303 +0200
+++ gcc/gcc/testsuite/gfortran.dg/coarray_21.f90 2011-05-07 11:44:14.000000000 +0200
@@ -0,0 +1,17 @@
+! { dg-do compile }
+! { dg-options "-fcoarray=single" }
+!
+! PR fortran/18918
+!
+! Before scalar coarrays weren't regarded as scalar in the ME.
+!
+module mod_reduction
+ real :: g[*]
+contains
+ subroutine caf_reduce(x)
+ real, intent(in) :: x
+ g = x ! << usded to ICE
+ end
+end module
+
+! { dg-final { cleanup-modules "mod_reduction" } }