From 8df87c9e2c0a31c669625c4942d09b03d36c73e9 Mon Sep 17 00:00:00 2001 From: Thomas Koenig Date: Mon, 4 Oct 2021 22:34:53 +0200 Subject: Take memory from envirnoment variables; document those. --- gcc/fortran/gfortran.texi | 31 +++++++++++++++++++ gcc/fortran/invoke.texi | 9 +++++- libgfortran/caf_shared/coarraynative.c | 54 +++++++++++++++++++++++++++++++++- libgfortran/caf_shared/shared_memory.c | 12 +------- libgfortran/caf_shared/shared_memory.h | 2 +- 5 files changed, 94 insertions(+), 14 deletions(-) diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi index a54153b..6c5ed84 100644 --- a/gcc/fortran/gfortran.texi +++ b/gcc/fortran/gfortran.texi @@ -608,6 +608,8 @@ Malformed environment variables are silently ignored. * GFORTRAN_ERROR_BACKTRACE:: Show backtrace on run-time errors * GFORTRAN_FORMATTED_BUFFER_SIZE:: Buffer size for formatted files * GFORTRAN_UNFORMATTED_BUFFER_SIZE:: Buffer size for unformatted files +* GFORTRAN_NUM_IMAGES:: Number of images to for -fcoarray=shared +* GFORTRAN_SHARED_MEMORY_SIZE:: Memory for shared-memory coarrays @end menu @node TMPDIR @@ -793,6 +795,35 @@ The @env{GFORTRAN_UNFORMATTED_BUFFER_SIZE} environment variable specifies buffer size in bytes to be used for unformatted output. The default value is 131072. +@node GFORTRAN_NUM_IMAGES +@section @env{GFORTRAN_NUM_IMAGES}---Set number of images for shared-memory coarrays + +The @env{GFORTRAN_NUM_IMAGES} environment variable specifies the number +of images to be run for shared-memory coarrays, as an integer. The default +value is the number of CPUs on the system. + +@node GFORTRAN_SHARED_MEMORY_SIZE +@section @env{GFORTRAN_SHARED_MEMORY_SIZE}---Set size for shared-memory coarrays + +The @env{GFORTRAN_SHARED_MEMORY_SIZE} environment variable specifies +the size of the shared memory block to be allocated for shared +coarrays. It is safe on Linux and Darwin to make this larger than +needed. When specifying this value, keep in mind that part of the space +will not be available to the user program because of overhead. + +The format is an integer, optionally followed by @code{k} or @code{K} +for a unit of kilobytes, @code{m} or @code{M} for a unit of megabytes +and @code{g} or @code{G} for a unit of gitabytes. + +For example, if the size of all coarrays is known to be smaller than +50 megabyte, the syntax could be +@smallexample +$ GFORTRAN_SHARED_MEMORY_SIZE=80M ./a.out +@end smallexample + +The default is 256 kilobyte for 32-bit systems and 256 gigabyte for +64-bit systems. + @c ===================================================================== @c PART II: LANGUAGE REFERENCE @c ===================================================================== diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi index 0fb7e1a..e9f89cb 100644 --- a/gcc/fortran/invoke.texi +++ b/gcc/fortran/invoke.texi @@ -188,7 +188,7 @@ and warnings}. -fbounds-check -ftail-call-workaround -ftail-call-workaround=@var{n} @gol -fcheck-array-temporaries @gol -fcheck=@var{} @gol --fcoarray=@var{} -fexternal-blas -ff2c @gol +-fcoarray=@var{} -fexternal-blas -ff2c @gol -ffrontend-loop-interchange -ffrontend-optimize @gol -finit-character=@var{n} -finit-integer=@var{n} -finit-local-zero @gol -finit-derived -finit-logical=@var{} @gol @@ -1607,6 +1607,13 @@ Single-image mode, i.e. @code{num_images()} is always one. @item @samp{lib} Library-based coarray parallelization; a suitable GNU Fortran coarray library needs to be linked. + +@item @samp{shared} +This enables an experimental shared-memory implementation of +coarrays. Expect bugs and incomplete implementation. Currently, +this depends on POSIX shared mutexes, so this option is not supported +on systems which do not have them. There is no Windows implementation +at the moment. @end table diff --git a/libgfortran/caf_shared/coarraynative.c b/libgfortran/caf_shared/coarraynative.c index 1ae0c40..cf72433 100644 --- a/libgfortran/caf_shared/coarraynative.c +++ b/libgfortran/caf_shared/coarraynative.c @@ -35,6 +35,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include #define GFORTRAN_ENV_NUM_IMAGES "GFORTRAN_NUM_IMAGES" +#define GFORTRAN_ENV_SHARED_MEMORY_SIZE "GFORTRAN_SHARED_MEMORY_SIZE" nca_local_data *local = NULL; @@ -55,6 +56,54 @@ get_environ_image_num (void) return nimages; } +/* Get the amount of memory for the shared memory block. This is picked from + an environment variable. If that is not there, pick a reasonable default. + Note that on a 64-bit system which allows overcommit, there is no penalty in + reserving a large space and then not using it. */ + +static size_t +get_memory_size (void) +{ + char *e; + size_t sz = 0; + e = getenv (GFORTRAN_ENV_SHARED_MEMORY_SIZE); + if (e) + { + char *num, suffix; + int rv; + rv = sscanf (e, "%zu%1s",&sz, &suffix); + if (rv == 2) + { + switch (suffix) + { + case 'k': + case 'K': + sz *= ((size_t) 1) << 10; + break; + case 'm': + case 'M': + sz *= ((size_t) 1) << 20; + break; + case 'g': + case 'G': + sz *= ((size_t) 1) << 30; + break; + default: + sz = 0; + } + } + } + if (sz == 0) + { + /* Use 256 MB for 32-bit systems and 256 GB for 64-bit systems. */ + if (sizeof (size_t) == 4) + sz = ((size_t) 1) << 28; + else + sz = ((size_t) 1) << 38; + } + return sz; +} + /* Get a master. */ static master * @@ -79,6 +128,8 @@ get_master (void) void ensure_initialization (void) { + size_t shmem_size; + if (local) return; @@ -86,8 +137,9 @@ ensure_initialization (void) // that point? Maybe use // mmap(MAP_ANON) instead pagesize = sysconf (_SC_PAGE_SIZE); + shmem_size = round_to_pagesize (get_memory_size()); local->total_num_images = get_environ_image_num (); - shared_memory_init (&local->sm); + shared_memory_init (&local->sm, shmem_size); shared_memory_prepare (&local->sm); if (this_image.m == NULL) /* A bit of a hack, but we need the master early. */ diff --git a/libgfortran/caf_shared/shared_memory.c b/libgfortran/caf_shared/shared_memory.c index 0c0b36c..bc1a2e9 100644 --- a/libgfortran/caf_shared/shared_memory.c +++ b/libgfortran/caf_shared/shared_memory.c @@ -186,21 +186,11 @@ shared_memory_prepare (shared_memory_act **pmem) shared memory is stored at the beginning. */ void -shared_memory_init (shared_memory_act **pmem) +shared_memory_init (shared_memory_act **pmem, size_t initial_size) { shared_memory_act *mem; int fd; - /* Darwin does not appear to be able to grow shared memory segments. Choose - 256 GB; that will likely be enough. If not, the ftruncate will fail - noisily. */ - -#ifdef __APPLE__ - size_t initial_size = ((size_t) 1) << 38; -#else - size_t initial_size = round_to_pagesize (sizeof (global_shared_memory_meta)); -#endif - mem = malloc (get_shared_memory_act_size (1)); fd = get_shmem_fd (); diff --git a/libgfortran/caf_shared/shared_memory.h b/libgfortran/caf_shared/shared_memory.h index 09692fc..dd03227 100644 --- a/libgfortran/caf_shared/shared_memory.h +++ b/libgfortran/caf_shared/shared_memory.h @@ -53,7 +53,7 @@ typedef struct shared_mem_ptr ssize_t offset; } shared_mem_ptr; -void shared_memory_init (shared_memory *); +void shared_memory_init (shared_memory *, size_t); internal_proto (shared_memory_init); void shared_memory_prepare (shared_memory *); -- cgit v1.1