This patch adds documentation and DejaGNU test cases for GOMP_DYNAMIC_POLICY, a
new GCC-specific environment variable extending OMP_DYNAMIC to support
Juunansei's phantom-guided degree-of-parallelism (DoP) adaptation
(GOMP_DYNAMIC_POLICY=pvsched), as well as the default online-CPU-count-minus-
loadavg policy.

The documentation in libgomp.texi describes the behavior of Juunansei: when
phantom_average is positive, the DoP is lowered to relieve host-side
contention; when no phantoms are reported and idle_average has remained
positive for stability_requirement consecutive scheduler ticks, the DoP is
raised by the minimum idle_average observed over that window. The
documentation also notes that a watermark read failure safely falls back to
the default OMP_DYNAMIC heuristic.

The test cases in libgomp/testsuite/libgomp.c/ verify:
- GOMP_DYNAMIC_POLICY=pvsched resolves gomp_dynamic_policy to 1.
- GOMP_DYNAMIC_POLICY=default resolves gomp_dynamic_policy to 0.
- Case-insensitive parsing of the pvsched keyword (e.g. "PvSched").
- Rejection of an unrecognized value, falling back OMP_DYNAMIC default policy
libgomp/ChangeLog:

        * libgomp.texi (Environment Variables): Add GOMP_DYNAMIC_POLICY
        to the menu.
        (OMP_DYNAMIC): Cross-reference GOMP_DYNAMIC_POLICY.
        (GOMP_DYNAMIC_POLICY): New node.
        * testsuite/libgomp.c/pvsched_dynamic_policy-1.c: New test.
        * testsuite/libgomp.c/pvsched_dynamic_policy-2.c: New test.
        * testsuite/libgomp.c/pvsched_dynamic_policy-3.c: New test.
        * testsuite/libgomp.c/pvsched_dynamic_policy-4.c: New test.
---
 libgomp/libgomp.texi                          | 44 ++++++++++++++++++-
 .../libgomp.c/pvsched_dynamic_policy-1.c      | 20 +++++++++
 .../libgomp.c/pvsched_dynamic_policy-2.c      | 14 ++++++
 .../libgomp.c/pvsched_dynamic_policy-3.c      | 19 ++++++++
 .../libgomp.c/pvsched_dynamic_policy-4.c      | 16 +++++++
 5 files changed, 111 insertions(+), 2 deletions(-)
 create mode 100644 libgomp/testsuite/libgomp.c/pvsched_dynamic_policy-1.c
 create mode 100644 libgomp/testsuite/libgomp.c/pvsched_dynamic_policy-2.c
 create mode 100644 libgomp/testsuite/libgomp.c/pvsched_dynamic_policy-3.c
 create mode 100644 libgomp/testsuite/libgomp.c/pvsched_dynamic_policy-4.c

diff --git a/libgomp/libgomp.texi b/libgomp/libgomp.texi
index 8b7933198d0..6fa0882c3c0 100644
--- a/libgomp/libgomp.texi
+++ b/libgomp/libgomp.texi
@@ -4017,6 +4017,7 @@ variable is not set.
 * GOMP_STACKSIZE::          Set default thread stack size
 * GOMP_SPINCOUNT::          Set the busy-wait spin count
 * GOMP_WAIT_POLICY::        Select the phantom-guided wait policy
+* GOMP_DYNAMIC_POLICY::         Select the phantom-guided 
degree-of-parallelism policy
 * GOMP_RTEMS_THREAD_POOLS:: Set the RTEMS specific thread pools
 * GOMP_REVERSE_OFFLOAD_THREADS:: Set the maximum number of host threads
 @end menu
@@ -4231,9 +4232,9 @@ within a team.  The value of this environment variable 
shall be
 disabled by default.
 
 @item @emph{See also}:
-@ref{omp_set_dynamic}
+@ref{omp_set_dynamic}, @ref{GOMP_DYNAMIC_POLICY}
 
-@item @emph{Reference}: 
+@item @emph{Reference}:
 @uref{https://www.openmp.org, OpenMP specification v4.5}, Section 4.3
 @end table
 
@@ -4739,6 +4740,45 @@ Execution in Cloud VMs} (PhD thesis)
 
 
 
+@node GOMP_DYNAMIC_POLICY
+@section @env{GOMP_DYNAMIC_POLICY} -- Select the phantom-guided 
degree-of-parallelism policy
+@cindex Environment Variable
+@cindex Implementation specific setting
+@table @asis
+@item @emph{Description}:
+GCC-specific extension controlling the degree of parallelism (DoP) that
+libgomp's @code{gomp_dynamic_max_threads} resolves for a parallel
+region when @env{OMP_DYNAMIC} is enabled.
+
+When set to @code{PVSCHED}, @env{GOMP_DYNAMIC_POLICY} enables the
+Juunansei degree-of-parallelism algorithm, which replaces the default
+online-CPU-count-minus-loadavg heuristic with a decision driven by the
+same host-provided @code{phantom_average} metric used by
+@ref{GOMP_WAIT_POLICY}, together with a derived @code{idle_average}
+metric, both published over shared memory via
+@code{/dev/guest_ivshmem}.  When @code{phantom_average} is positive,
+Juunansei lowers the DoP by the number of phantoms detected; when no
+phantoms are reported, it holds the DoP steady and considers raising
+it by the minimum @code{idle_average} observed over a short, adaptive
+stability window of consecutive scheduler ticks.  If the shared-memory
+channel cannot be established, or a watermark read fails, libgomp
+silently and permanently falls back to the default heuristic for the
+remainder of the run.
+
+When set to @code{DEFAULT}, or left undefined, libgomp uses the
+default online-CPU-count-minus-loadavg heuristic.
+
+@item @emph{See also}:
+@ref{OMP_DYNAMIC}, @ref{GOMP_WAIT_POLICY}
+
+@item @emph{Reference}:
+Himadri Chhaya-Shailesh,
+@uref{https://inria.hal.science/tel-05438117v2, Scheduler Guided OpenMP
+Execution in Cloud VMs} (PhD thesis)
+@end table
+
+
+
 @node GOMP_RTEMS_THREAD_POOLS
 @section @env{GOMP_RTEMS_THREAD_POOLS} -- Set the RTEMS specific thread pools
 @cindex Environment Variable
diff --git a/libgomp/testsuite/libgomp.c/pvsched_dynamic_policy-1.c 
b/libgomp/testsuite/libgomp.c/pvsched_dynamic_policy-1.c
new file mode 100644
index 00000000000..94c6a3d17dc
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/pvsched_dynamic_policy-1.c
@@ -0,0 +1,20 @@
+/* Verify GOMP_DYNAMIC_POLICY=pvsched is accepted by parse_dynamic_policy()
+   in env.c's initialize_env().  gomp_dynamic_policy ends up 1 if
+   gomp_pvsched_init() succeeds (the /dev/guest_ivshmem device is present)
+   or 0 if it falls back (the device is absent, as on a regular test
+   machine); -1 is the only value that means the env var itself was
+   rejected, so that's what this test checks, same as
+   pvsched_wait_policy-*.c do for GOMP_WAIT_POLICY.  */
+/* { dg-do run } */
+/* { dg-additional-options "-Wl,-Bstatic,-lgomp,-Bdynamic" } */
+/* { dg-set-target-env-var GOMP_DYNAMIC_POLICY "pvsched" } */
+
+extern int gomp_dynamic_policy;
+
+int
+main (void)
+{
+  if (gomp_dynamic_policy == -1)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/pvsched_dynamic_policy-2.c 
b/libgomp/testsuite/libgomp.c/pvsched_dynamic_policy-2.c
new file mode 100644
index 00000000000..53ff7b24172
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/pvsched_dynamic_policy-2.c
@@ -0,0 +1,14 @@
+/* Verify GOMP_DYNAMIC_POLICY=default resolves gomp_dynamic_policy to 0.  */
+/* { dg-do run } */
+/* { dg-additional-options "-Wl,-Bstatic,-lgomp,-Bdynamic" } */
+/* { dg-set-target-env-var GOMP_DYNAMIC_POLICY "default" } */
+
+extern int gomp_dynamic_policy;
+
+int
+main (void)
+{
+  if (gomp_dynamic_policy != 0)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/pvsched_dynamic_policy-3.c 
b/libgomp/testsuite/libgomp.c/pvsched_dynamic_policy-3.c
new file mode 100644
index 00000000000..0bcd580a002
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/pvsched_dynamic_policy-3.c
@@ -0,0 +1,19 @@
+/* Verify GOMP_DYNAMIC_POLICY parsing is case-insensitive: "PvSched" must
+   be recognized as the pvsched keyword, not rejected.  gomp_dynamic_policy
+   ends up 1 or 0 depending on whether gomp_pvsched_init() can open
+   /dev/guest_ivshmem on this machine; -1 is the only value that means
+   parsing itself rejected the value, so that's what this test checks,
+   same as pvsched_wait_policy-*.c do for GOMP_WAIT_POLICY.  */
+/* { dg-do run } */
+/* { dg-additional-options "-Wl,-Bstatic,-lgomp,-Bdynamic" } */
+/* { dg-set-target-env-var GOMP_DYNAMIC_POLICY "PvSched" } */
+
+extern int gomp_dynamic_policy;
+
+int
+main (void)
+{
+  if (gomp_dynamic_policy == -1)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/pvsched_dynamic_policy-4.c 
b/libgomp/testsuite/libgomp.c/pvsched_dynamic_policy-4.c
new file mode 100644
index 00000000000..1e7b65329c4
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/pvsched_dynamic_policy-4.c
@@ -0,0 +1,16 @@
+/* Verify an unrecognized GOMP_DYNAMIC_POLICY value is rejected and
+   safely falls back to the default (-1).  */
+/* { dg-do run } */
+/* { dg-additional-options "-Wl,-Bstatic,-lgomp,-Bdynamic" } */
+/* { dg-set-target-env-var GOMP_DYNAMIC_POLICY "bogus" } */
+/* { dg-output "Invalid value for environment variable GOMP_DYNAMIC_POLICY" } 
*/
+
+extern int gomp_dynamic_policy;
+
+int
+main (void)
+{
+  if (gomp_dynamic_policy != -1)
+    __builtin_abort ();
+  return 0;
+}
-- 
2.34.1

Reply via email to