[OpenMP] Make use of sched_yield optional in runtime

This patch cleans up the yielding code and makes it optional. An
environment variable, KMP_USE_YIELD, was added. Yielding is still
on by default (KMP_USE_YIELD=1), but can be turned off completely
(KMP_USE_YIELD=0), or turned on only when oversubscription is detected
(KMP_USE_YIELD=2). Note that oversubscription cannot always be detected
by the runtime (for example, when the runtime is initialized and the
process forks, oversubscription cannot be detected currently over
multiple instances of the runtime).

Because yielding can be controlled by user now, the library mode
settings (from KMP_LIBRARY) for throughput and turnaround have been
adjusted by altering blocktime, unless that was also explicitly set.

In the original code, there were a number of places where a double yield
might have been done under oversubscription. This version checks
oversubscription and if that's not going to yield, then it does
the spin check.

Patch by Terry Wilmarth

Differential Revision: https://reviews.llvm.org/D58148


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@355120 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jonathan Peyton
2019-02-28 19:11:29 +00:00
parent acb2548dde
commit bbb6f01707
19 changed files with 184 additions and 386 deletions
+7 -24
View File
@@ -327,7 +327,7 @@ void __kmp_infinite_loop(void) {
static int done = FALSE;
while (!done) {
KMP_YIELD(1);
KMP_YIELD(TRUE);
}
}
@@ -672,24 +672,6 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved) {
#endif /* KMP_OS_WINDOWS */
#endif /* KMP_DYNAMIC_LIB */
/* Change the library type to "status" and return the old type */
/* called from within initialization routines where __kmp_initz_lock is held */
int __kmp_change_library(int status) {
int old_status;
old_status = __kmp_yield_init &
1; // check whether KMP_LIBRARY=throughput (even init count)
if (status) {
__kmp_yield_init |= 1; // throughput => turnaround (odd init count)
} else {
__kmp_yield_init &= ~1; // turnaround => throughput (even init count)
}
return old_status; // return previous setting of whether
// KMP_LIBRARY=throughput
}
/* __kmp_parallel_deo -- Wait until it's our turn. */
void __kmp_parallel_deo(int *gtid_ref, int *cid_ref, ident_t *loc_ref) {
int gtid = *gtid_ref;
@@ -708,8 +690,8 @@ void __kmp_parallel_deo(int *gtid_ref, int *cid_ref, ident_t *loc_ref) {
#ifdef BUILD_PARALLEL_ORDERED
if (!team->t.t_serialized) {
KMP_MB();
KMP_WAIT_YIELD(&team->t.t_ordered.dt.t_value, __kmp_tid_from_gtid(gtid),
KMP_EQ, NULL);
KMP_WAIT(&team->t.t_ordered.dt.t_value, __kmp_tid_from_gtid(gtid), KMP_EQ,
NULL);
KMP_MB();
}
#endif /* BUILD_PARALLEL_ORDERED */
@@ -7735,13 +7717,14 @@ void __kmp_aux_set_library(enum library_type arg) {
switch (__kmp_library) {
case library_serial: {
KMP_INFORM(LibraryIsSerial);
(void)__kmp_change_library(TRUE);
} break;
case library_turnaround:
(void)__kmp_change_library(TRUE);
if (__kmp_use_yield == 1 && !__kmp_use_yield_exp_set)
__kmp_use_yield = 2; // only yield when oversubscribed
break;
case library_throughput:
(void)__kmp_change_library(FALSE);
if (__kmp_dflt_blocktime == KMP_MAX_BLOCKTIME)
__kmp_dflt_blocktime = 200;
break;
default:
KMP_FATAL(UnknownLibraryType, arg);