OpenMP 5.1: Add proc-bind 'primary' support

In OpenMP 5.1 "master thread" was changed to "primary thread" and
the proc_bind clause and the OMP_PROC_BIND environment variable
now take 'primary' as argument as alias for 'master', while the
latter is deprecated.
This commit accepts 'primary' and adds the named constant
omp_proc_bind_primary and changes 'master thread' in the
documentation; however, given that not even OpenMP 5.0 is
fully supported, omp_display_env and the dumps currently
still output 'master' and there is no deprecation warning
when using the 'master' in the proc_bind clause.

gcc/c/ChangeLog:

	* c-parser.c (c_parser_omp_clause_proc_bind): Accept
	'primary' as alias for 'master'.

gcc/cp/ChangeLog:

	* parser.c (cp_parser_omp_clause_proc_bind): Accept
	'primary' as alias for 'master'.

gcc/fortran/ChangeLog:

	* gfortran.h (gfc_omp_proc_bind_kind): Add OMP_PROC_BIND_PRIMARY.
	* dump-parse-tree.c (show_omp_clauses): Add TODO comment to
	change 'master' to 'primary' in proc_bind for OpenMP 5.1.
	* intrinsic.texi (OMP_LIB): Mention OpenMP 5.1; add
	omp_proc_bind_primary.
	* openmp.c (gfc_match_omp_clauses): Accept
	'primary' as alias for 'master'.
	* trans-openmp.c (gfc_trans_omp_clauses): Handle
	OMP_PROC_BIND_PRIMARY.

gcc/ChangeLog:

	* tree-core.h (omp_clause_proc_bind_kind): Add
	OMP_CLAUSE_PROC_BIND_PRIMARY.
	* tree-pretty-print.c (dump_omp_clause): Add TODO comment to
	change 'master' to 'primary' in proc_bind for OpenMP 5.1.

libgomp/ChangeLog:

	* env.c (parse_bind_var): Accept 'primary' as alias for
	'master'.
	(omp_display_env): Add TODO comment to
	change 'master' to 'primary' in proc_bind for OpenMP 5.1.
	* libgomp.texi: Change 'master thread' to 'primary thread'
	in line with OpenMP 5.1.
	(omp_get_proc_bind): Add omp_proc_bind_primary and note that
	omp_proc_bind_master is an alias of it.
	(OMP_PROC_BIND): Mention 'PRIMARY'.
	* omp.h.in (__GOMP_DEPRECATED_5_1): Define.
	(omp_proc_bind_primary): Add.
	(omp_proc_bind_master): Deprecate for OpenMP 5.1.
	* omp_lib.f90.in (omp_proc_bind_primary): Add.
	(omp_proc_bind_master): Deprecate for OpenMP 5.1.
	* omp_lib.h.in (omp_proc_bind_primary): Add.
	* testsuite/libgomp.c/affinity-1.c: Check that
	'primary' works and is identical to 'master'.

gcc/testsuite/ChangeLog:

	* c-c++-common/gomp/pr61486-2.c: Duplicate one proc_bind(master)
	testcase and test proc_bind(primary) instead.
	* gfortran.dg/gomp/affinity-1.f90: Likewise.
This commit is contained in:
Tobias Burnus 2021-08-12 15:48:28 +02:00
parent 2d7967a10c
commit 432de08498
17 changed files with 99 additions and 33 deletions

View File

@ -15959,7 +15959,8 @@ c_parser_omp_clause_dist_schedule (c_parser *parser, tree list)
proc_bind ( proc-bind-kind )
proc-bind-kind:
master | close | spread */
primary | master | close | spread
where OpenMP 5.1 added 'primary' and deprecated the alias 'master'. */
static tree
c_parser_omp_clause_proc_bind (c_parser *parser, tree list)
@ -15975,7 +15976,9 @@ c_parser_omp_clause_proc_bind (c_parser *parser, tree list)
if (c_parser_next_token_is (parser, CPP_NAME))
{
const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
if (strcmp ("master", p) == 0)
if (strcmp ("primary", p) == 0)
kind = OMP_CLAUSE_PROC_BIND_PRIMARY;
else if (strcmp ("master", p) == 0)
kind = OMP_CLAUSE_PROC_BIND_MASTER;
else if (strcmp ("close", p) == 0)
kind = OMP_CLAUSE_PROC_BIND_CLOSE;

View File

@ -39020,7 +39020,8 @@ cp_parser_omp_clause_dist_schedule (cp_parser *parser, tree list,
proc_bind ( proc-bind-kind )
proc-bind-kind:
master | close | spread */
primary | master | close | spread
where OpenMP 5.1 added 'primary' and deprecated the alias 'master'. */
static tree
cp_parser_omp_clause_proc_bind (cp_parser *parser, tree list,
@ -39037,7 +39038,9 @@ cp_parser_omp_clause_proc_bind (cp_parser *parser, tree list,
tree id = cp_lexer_peek_token (parser->lexer)->u.value;
const char *p = IDENTIFIER_POINTER (id);
if (strcmp ("master", p) == 0)
if (strcmp ("primary", p) == 0)
kind = OMP_CLAUSE_PROC_BIND_PRIMARY;
else if (strcmp ("master", p) == 0)
kind = OMP_CLAUSE_PROC_BIND_MASTER;
else if (strcmp ("close", p) == 0)
kind = OMP_CLAUSE_PROC_BIND_CLOSE;

View File

@ -1712,6 +1712,7 @@ show_omp_clauses (gfc_omp_clauses *omp_clauses)
const char *type;
switch (omp_clauses->proc_bind)
{
case OMP_PROC_BIND_PRIMARY: type = "PRIMARY"; break;
case OMP_PROC_BIND_MASTER: type = "MASTER"; break;
case OMP_PROC_BIND_SPREAD: type = "SPREAD"; break;
case OMP_PROC_BIND_CLOSE: type = "CLOSE"; break;

View File

@ -1362,6 +1362,7 @@ enum gfc_omp_default_sharing
enum gfc_omp_proc_bind_kind
{
OMP_PROC_BIND_UNKNOWN,
OMP_PROC_BIND_PRIMARY,
OMP_PROC_BIND_MASTER,
OMP_PROC_BIND_SPREAD,
OMP_PROC_BIND_CLOSE

View File

@ -15293,8 +15293,9 @@ with the following options: @code{-fno-unsafe-math-optimizations
@section OpenMP Modules @code{OMP_LIB} and @code{OMP_LIB_KINDS}
@table @asis
@item @emph{Standard}:
OpenMP Application Program Interface v4.5 and
OpenMP Application Program Interface v5.0 (partially supported).
OpenMP Application Program Interface v4.5,
OpenMP Application Program Interface v5.0 (partially supported) and
OpenMP Application Program Interface v5.1 (partially supported).
@end table
The OpenMP Fortran runtime library routines are provided both in
@ -15357,6 +15358,7 @@ kind @code{omp_proc_bind_kind}:
@table @asis
@item @code{omp_proc_bind_false}
@item @code{omp_proc_bind_true}
@item @code{omp_proc_bind_primary}
@item @code{omp_proc_bind_master}
@item @code{omp_proc_bind_close}
@item @code{omp_proc_bind_spread}

View File

@ -2231,7 +2231,10 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
if ((mask & OMP_CLAUSE_PROC_BIND)
&& c->proc_bind == OMP_PROC_BIND_UNKNOWN)
{
if (gfc_match ("proc_bind ( master )") == MATCH_YES)
/* Primary is new and master is deprecated in OpenMP 5.1. */
if (gfc_match ("proc_bind ( primary )") == MATCH_YES)
c->proc_bind = OMP_PROC_BIND_MASTER;
else if (gfc_match ("proc_bind ( master )") == MATCH_YES)
c->proc_bind = OMP_PROC_BIND_MASTER;
else if (gfc_match ("proc_bind ( spread )") == MATCH_YES)
c->proc_bind = OMP_PROC_BIND_SPREAD;

View File

@ -3865,6 +3865,9 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_PROC_BIND);
switch (clauses->proc_bind)
{
case OMP_PROC_BIND_PRIMARY:
OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_PRIMARY;
break;
case OMP_PROC_BIND_MASTER:
OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_MASTER;
break;

View File

@ -216,6 +216,19 @@ test (int n, int o, int p, int q, int r, int s, int *pp)
s = i * 10;
}
#pragma omp target device (n + 1) if (n != 6)map(from:n) map(alloc:a[2:o-2])
#pragma omp teams distribute parallel for simd if (n != 6)default(shared) \
private (p) firstprivate (q) shared (n) reduction (+: r) \
thread_limit (n * 2) dist_schedule (static, 4) num_threads (n + 4) \
proc_bind (primary) lastprivate (s) schedule (static, 8) \
num_teams (n + 4) safelen(16) linear(i:1) aligned (pp:4)
for (i = 0; i < 10; i++)
{
r = r + 1;
p = q;
a[2+i] = p + q;
s = i * 10;
}
#pragma omp target device (n + 1) if (n != 6)map(from:n) map(alloc:a[2:o-2])
#pragma omp teams distribute simd default(shared) \
private (p) firstprivate (q) shared (n) reduction (+: r) \
thread_limit (n * 2) dist_schedule (static, 4) collapse (2) \

View File

@ -9,6 +9,15 @@
j = 8
end do
!$omp end parallel do
!$omp parallel do default(none)proc_bind(primary)shared(a)
do i = 1, 10
j = 4
do j = 1, 10
a(i, j) = i + j
end do
j = 8
end do
!$omp end parallel do
!$omp parallel proc_bind (close)
!$omp parallel default(none) proc_bind (spread) firstprivate(a) private (i)
do i = 1, 10

View File

@ -1498,6 +1498,7 @@ enum omp_clause_proc_bind_kind
/* Numbers should match omp_proc_bind_t enum in omp.h. */
OMP_CLAUSE_PROC_BIND_FALSE = 0,
OMP_CLAUSE_PROC_BIND_TRUE = 1,
OMP_CLAUSE_PROC_BIND_PRIMARY = 2,
OMP_CLAUSE_PROC_BIND_MASTER = 2,
OMP_CLAUSE_PROC_BIND_CLOSE = 3,
OMP_CLAUSE_PROC_BIND_SPREAD = 4,

View File

@ -1008,6 +1008,8 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
switch (OMP_CLAUSE_PROC_BIND_KIND (clause))
{
case OMP_CLAUSE_PROC_BIND_MASTER:
/* Same enum value: case OMP_CLAUSE_PROC_BIND_PRIMARY: */
/* TODO: Change to 'primary' for OpenMP 5.1. */
pp_string (pp, "master");
break;
case OMP_CLAUSE_PROC_BIND_CLOSE:

View File

@ -437,6 +437,7 @@ parse_bind_var (const char *name, char *p1stvalue,
{ "false", 5, omp_proc_bind_false },
{ "true", 4, omp_proc_bind_true },
{ "master", 6, omp_proc_bind_master },
{ "primary", 7, omp_proc_bind_primary },
{ "close", 5, omp_proc_bind_close },
{ "spread", 6, omp_proc_bind_spread }
};
@ -450,14 +451,14 @@ parse_bind_var (const char *name, char *p1stvalue,
if (*env == '\0')
goto invalid;
for (i = 0; i < 5; i++)
for (i = 0; i < 6; i++)
if (strncasecmp (env, kinds[i].name, kinds[i].len) == 0)
{
value = kinds[i].kind;
env += kinds[i].len;
break;
}
if (i == 5)
if (i == 6)
goto invalid;
while (isspace ((unsigned char) *env))
@ -497,14 +498,14 @@ parse_bind_var (const char *name, char *p1stvalue,
if (*env == '\0')
goto invalid;
for (i = 2; i < 5; i++)
for (i = 2; i < 6; i++)
if (strncasecmp (env, kinds[i].name, kinds[i].len) == 0)
{
value = kinds[i].kind;
env += kinds[i].len;
break;
}
if (i == 5)
if (i == 6)
goto invalid;
values[nvalues++] = value;
@ -1277,7 +1278,7 @@ omp_display_env (int verbose)
fputs ("TRUE", stderr);
break;
case omp_proc_bind_master:
fputs ("MASTER", stderr);
fputs ("MASTER", stderr); /* TODO: Change to PRIMARY for OpenMP 5.1. */
break;
case omp_proc_bind_close:
fputs ("CLOSE", stderr);
@ -1290,7 +1291,7 @@ omp_display_env (int verbose)
switch (gomp_bind_var_list[i])
{
case omp_proc_bind_master:
fputs (",MASTER", stderr);
fputs (",MASTER", stderr); /* TODO: Change to PRIMARY for OpenMP 5.1. */
break;
case omp_proc_bind_close:
fputs (",CLOSE", stderr);

View File

@ -660,8 +660,9 @@ one thread per CPU online is used.
@item @emph{Description}:
This functions returns the currently active thread affinity policy, which is
set via @env{OMP_PROC_BIND}. Possible values are @code{omp_proc_bind_false},
@code{omp_proc_bind_true}, @code{omp_proc_bind_master},
@code{omp_proc_bind_close} and @code{omp_proc_bind_spread}.
@code{omp_proc_bind_true}, @code{omp_proc_bind_primary},
@code{omp_proc_bind_master}, @code{omp_proc_bind_close} and @code{omp_proc_bind_spread},
where @code{omp_proc_bind_master} is an alias for @code{omp_proc_bind_primary}.
@item @emph{C/C++}:
@multitable @columnfractions .20 .80
@ -822,7 +823,7 @@ Returns a unique thread identification number within the current team.
In a sequential parts of the program, @code{omp_get_thread_num}
always returns 0. In parallel regions the return value varies
from 0 to @code{omp_get_num_threads}-1 inclusive. The return
value of the master thread of a team is always 0.
value of the primary thread of a team is always 0.
@item @emph{C/C++}:
@multitable @columnfractions .20 .80
@ -1670,11 +1671,12 @@ nesting by default. If undefined one thread per CPU is used.
Specifies whether threads may be moved between processors. If set to
@code{TRUE}, OpenMP theads should not be moved; if set to @code{FALSE}
they may be moved. Alternatively, a comma separated list with the
values @code{MASTER}, @code{CLOSE} and @code{SPREAD} can be used to specify
the thread affinity policy for the corresponding nesting level. With
@code{MASTER} the worker threads are in the same place partition as the
master thread. With @code{CLOSE} those are kept close to the master thread
in contiguous place partitions. And with @code{SPREAD} a sparse distribution
values @code{PRIMARY}, @code{MASTER}, @code{CLOSE} and @code{SPREAD} can
be used to specify the thread affinity policy for the corresponding nesting
level. With @code{PRIMARY} and @code{MASTER} the worker threads are in the
same place partition as the primary thread. With @code{CLOSE} those are
kept close to the primary thread in contiguous place partitions. And
with @code{SPREAD} a sparse distribution
across the place partitions is used. Specifying more than one item in the
list will automatically enable nesting by default.
@ -1951,23 +1953,23 @@ instance.
@item @code{$<priority>} is an optional priority for the worker threads of a
thread pool according to @code{pthread_setschedparam}. In case a priority
value is omitted, then a worker thread will inherit the priority of the OpenMP
master thread that created it. The priority of the worker thread is not
changed after creation, even if a new OpenMP master thread using the worker has
primary thread that created it. The priority of the worker thread is not
changed after creation, even if a new OpenMP primary thread using the worker has
a different priority.
@item @code{@@<scheduler-name>} is the scheduler instance name according to the
RTEMS application configuration.
@end itemize
In case no thread pool configuration is specified for a scheduler instance,
then each OpenMP master thread of this scheduler instance will use its own
then each OpenMP primary thread of this scheduler instance will use its own
dynamically allocated thread pool. To limit the worker thread count of the
thread pools, each OpenMP master thread must call @code{omp_set_num_threads}.
thread pools, each OpenMP primary thread must call @code{omp_set_num_threads}.
@item @emph{Example}:
Lets suppose we have three scheduler instances @code{IO}, @code{WRK0}, and
@code{WRK1} with @env{GOMP_RTEMS_THREAD_POOLS} set to
@code{"1@@WRK0:3$4@@WRK1"}. Then there are no thread pool restrictions for
scheduler instance @code{IO}. In the scheduler instance @code{WRK0} there is
one thread pool available. Since no priority is specified for this scheduler
instance, the worker thread inherits the priority of the OpenMP master thread
instance, the worker thread inherits the priority of the OpenMP primary thread
that created it. In the scheduler instance @code{WRK1} there are three thread
pools available and their worker threads run at priority four.
@end table
@ -3881,7 +3883,7 @@ if (omp_get_thread_num () == 0)
@end smallexample
Alternately, we generate two copies of the parallel subfunction
and only include this in the version run by the master thread.
and only include this in the version run by the primary thread.
Surely this is not worthwhile though...
@ -4018,7 +4020,7 @@ broadcast would have to happen via SINGLE machinery instead.
The private struct mentioned in the previous section should have
a pointer to an array of the type of the variable, indexed by the
thread's @var{team_id}. The thread stores its final value into the
array, and after the barrier, the master thread iterates over the
array, and after the barrier, the primary thread iterates over the
array to collect the values.

View File

@ -32,6 +32,12 @@
# define __GOMP_DEPRECATED_5_0
#endif
#if defined(__GNUC__) && _OPENMP >= 202011
# define __GOMP_DEPRECATED_5_1 __attribute__((__deprecated__))
#else
# define __GOMP_DEPRECATED_5_1
#endif
#ifndef _LIBGOMP_OMP_LOCK_DEFINED
#define _LIBGOMP_OMP_LOCK_DEFINED 1
/* These two structures get edited by the libgomp build process to
@ -64,7 +70,9 @@ typedef enum omp_proc_bind_t
{
omp_proc_bind_false = 0,
omp_proc_bind_true = 1,
omp_proc_bind_master = 2,
omp_proc_bind_primary = 2,
omp_proc_bind_master __GOMP_DEPRECATED_5_1
= omp_proc_bind_primary,
omp_proc_bind_close = 3,
omp_proc_bind_spread = 4
} omp_proc_bind_t;

View File

@ -48,6 +48,8 @@
parameter :: omp_proc_bind_false = 0
integer (omp_proc_bind_kind), &
parameter :: omp_proc_bind_true = 1
integer (omp_proc_bind_kind), &
parameter :: omp_proc_bind_primary = 2
integer (omp_proc_bind_kind), &
parameter :: omp_proc_bind_master = 2
integer (omp_proc_bind_kind), &
@ -670,6 +672,10 @@
#if _OPENMP >= 201811
!GCC$ ATTRIBUTES DEPRECATED :: omp_get_nested, omp_set_nested
#endif
#if _OPENMP >= 202011
!GCC$ ATTRIBUTES DEPRECATED :: omp_proc_bind_master
#endif
end module omp_lib

View File

@ -40,11 +40,13 @@
parameter (omp_proc_bind_kind = 4)
integer (omp_proc_bind_kind) omp_proc_bind_false
integer (omp_proc_bind_kind) omp_proc_bind_true
integer (omp_proc_bind_kind) omp_proc_bind_primary
integer (omp_proc_bind_kind) omp_proc_bind_master
integer (omp_proc_bind_kind) omp_proc_bind_close
integer (omp_proc_bind_kind) omp_proc_bind_spread
parameter (omp_proc_bind_false = 0)
parameter (omp_proc_bind_true = 1)
parameter (omp_proc_bind_primary = 2)
parameter (omp_proc_bind_master = 2)
parameter (omp_proc_bind_close = 3)
parameter (omp_proc_bind_spread = 4)

View File

@ -183,20 +183,26 @@ main ()
int test_false = env_proc_bind && strcmp (env_proc_bind, "false") == 0;
int test_true = env_proc_bind && strcmp (env_proc_bind, "true") == 0;
int test_spread_master_close
= env_proc_bind && strcmp (env_proc_bind, "spread,master,close") == 0;
= (env_proc_bind
&& (strcmp (env_proc_bind, "spread,master,close") == 0
|| strcmp (env_proc_bind, "spread,primary,close") == 0));
char *env_places = getenv ("OMP_PLACES");
int test_places = 0;
if (omp_proc_bind_master != omp_proc_bind_primary)
abort ();
#ifdef DO_FORK
if (env_places == NULL && contig_cpucount >= 8 && test_false
&& getenv ("GOMP_AFFINITY") == NULL)
{
int i, j, status;
pid_t pid;
for (j = 0; j < 2; j++)
for (j = 0; j < 3; j++)
{
if (setenv ("OMP_PROC_BIND", j ? "spread,master,close" : "true", 1)
< 0)
if (setenv ("OMP_PROC_BIND",
j > 1 ? "spread,primary,close"
: (j ? "spread,master,close" : "true"), 1) < 0)
break;
for (i = sizeof (places_array) / sizeof (places_array[0]) - 1;
i; --i)