From d7b12004bd7d6d9a592f1773101cbedd9daf8492 Mon Sep 17 00:00:00 2001 From: AndreyChurbanov Date: Mon, 1 Feb 2021 22:54:11 +0300 Subject: [PATCH] [OpenMP] libomp: implement nteams-var and teams-thread-limit-var ICVs The change includes OMP_NUM_TEAMS, OMP_TEAMS_THREAD_LIMIT env variables, omp_set_num_teams, omp_get_max_teams, omp_set_teams_thread_limit, omp_get_teams_thread_limit routines. Differential Revision: https://reviews.llvm.org/D95003 --- openmp/runtime/src/dllexports | 4 ++ openmp/runtime/src/include/omp.h.var | 6 +++ openmp/runtime/src/include/omp_lib.f90.var | 20 +++++++++ openmp/runtime/src/include/omp_lib.h.var | 22 ++++++++++ openmp/runtime/src/kmp.h | 6 +++ openmp/runtime/src/kmp_ftn_entry.h | 43 +++++++++++++++++++ openmp/runtime/src/kmp_ftn_os.h | 16 +++++++ openmp/runtime/src/kmp_global.cpp | 2 + openmp/runtime/src/kmp_runtime.cpp | 28 ++++++++++-- openmp/runtime/src/kmp_settings.cpp | 31 +++++++++++++ openmp/runtime/test/api/omp_nteams_api.c | 26 +++++++++++ openmp/runtime/test/api/omp_nteams_api_env.c | 24 +++++++++++ openmp/runtime/test/api/omp_nteams_api_env2.c | 26 +++++++++++ 13 files changed, 251 insertions(+), 3 deletions(-) create mode 100644 openmp/runtime/test/api/omp_nteams_api.c create mode 100644 openmp/runtime/test/api/omp_nteams_api_env.c create mode 100644 openmp/runtime/test/api/omp_nteams_api_env2.c diff --git a/openmp/runtime/src/dllexports b/openmp/runtime/src/dllexports index 1c29ca90657a..8f9c73f637d0 100644 --- a/openmp/runtime/src/dllexports +++ b/openmp/runtime/src/dllexports @@ -537,6 +537,10 @@ kmp_set_disp_num_buffers 890 omp_pause_resource_all 757 omp_get_supported_active_levels 758 omp_fulfill_event 759 + omp_set_num_teams 802 + omp_get_max_teams 803 + omp_set_teams_thread_limit 804 + omp_get_teams_thread_limit 805 omp_display_env 733 omp_calloc 776 omp_realloc 777 diff --git a/openmp/runtime/src/include/omp.h.var b/openmp/runtime/src/include/omp.h.var index 4d055f905bcb..eff94ca21029 100644 --- a/openmp/runtime/src/include/omp.h.var +++ b/openmp/runtime/src/include/omp.h.var @@ -442,6 +442,12 @@ extern int __KAI_KMPC_CONVENTION omp_get_supported_active_levels(void); + /* OpenMP 5.1 */ + extern void __KAI_KMPC_CONVENTION omp_set_num_teams(int num_teams); + extern int __KAI_KMPC_CONVENTION omp_get_max_teams(void); + extern void __KAI_KMPC_CONVENTION omp_set_teams_thread_limit(int limit); + extern int __KAI_KMPC_CONVENTION omp_get_teams_thread_limit(void); + /* OpenMP 5.1 Display Environment */ extern void omp_display_env(int verbose); diff --git a/openmp/runtime/src/include/omp_lib.f90.var b/openmp/runtime/src/include/omp_lib.f90.var index 2fc8d7c3daa4..ef2d656924ca 100644 --- a/openmp/runtime/src/include/omp_lib.f90.var +++ b/openmp/runtime/src/include/omp_lib.f90.var @@ -504,6 +504,26 @@ integer (kind=kmp_size_t_kind) :: omp_capture_affinity end function omp_capture_affinity + subroutine omp_set_num_teams(num_teams) bind(c) + use omp_lib_kinds + integer (kind=omp_integer_kind), value :: num_teams + end subroutine omp_set_num_teams + + function omp_get_max_teams() bind(c) + use omp_lib_kinds + integer (kind=omp_integer_kind) omp_get_max_teams + end function omp_get_max_teams + + subroutine omp_set_teams_thread_limit(thread_limit) bind(c) + use omp_lib_kinds + integer (kind=omp_integer_kind), value :: thread_limit + end subroutine omp_set_teams_thread_limit + + function omp_get_teams_thread_limit() bind(c) + use omp_lib_kinds + integer (kind=omp_integer_kind) omp_get_teams_thread_limit + end function omp_get_teams_thread_limit + subroutine omp_display_env(verbose) bind(c) use omp_lib_kinds logical (kind=omp_logical_kind), value :: verbose diff --git a/openmp/runtime/src/include/omp_lib.h.var b/openmp/runtime/src/include/omp_lib.h.var index 3fb2d25b15f1..0f6c715fe752 100644 --- a/openmp/runtime/src/include/omp_lib.h.var +++ b/openmp/runtime/src/include/omp_lib.h.var @@ -582,6 +582,28 @@ integer (kind=kmp_size_t_kind) :: omp_capture_affinity end function omp_capture_affinity + subroutine omp_set_num_teams(num_teams) bind(c) + import + integer (kind=omp_integer_kind), value :: num_teams + end subroutine omp_set_num_teams + + function omp_get_max_teams() bind(c) + import + integer (kind=omp_integer_kind) omp_get_max_teams + end function omp_get_max_teams + + subroutine omp_set_teams_thread_limit(thread_limit) bind(c) + import + use omp_lib_kinds + integer (kind=omp_integer_kind), value :: thread_limit + end subroutine omp_set_teams_thread_limit + + function omp_get_teams_thread_limit() bind(c) + import + use omp_lib_kinds + integer (kind=omp_integer_kind) omp_get_teams_thread_limit + end function omp_get_teams_thread_limit + subroutine omp_display_env(verbose) bind(c) import logical (kind=omp_logical_kind), value :: verbose diff --git a/openmp/runtime/src/kmp.h b/openmp/runtime/src/kmp.h index 163dc0e26ea1..1c84def4c038 100644 --- a/openmp/runtime/src/kmp.h +++ b/openmp/runtime/src/kmp.h @@ -3153,6 +3153,8 @@ extern const char *__kmp_speculative_statsfile; extern int __kmp_display_env; /* TRUE or FALSE */ extern int __kmp_display_env_verbose; /* TRUE if OMP_DISPLAY_ENV=VERBOSE */ extern int __kmp_omp_cancellation; /* TRUE or FALSE */ +extern int __kmp_nteams; +extern int __kmp_teams_thread_limit; /* ------------------------------------------------------------------------- */ @@ -3847,6 +3849,10 @@ KMP_EXPORT void __kmpc_task_reduction_modifier_fini(ident_t *loc, int gtid, KMP_EXPORT kmp_int32 __kmpc_omp_reg_task_with_affinity( ident_t *loc_ref, kmp_int32 gtid, kmp_task_t *new_task, kmp_int32 naffins, kmp_task_affinity_info_t *affin_list); +KMP_EXPORT void __kmp_set_num_teams(int num_teams); +KMP_EXPORT int __kmp_get_max_teams(void); +KMP_EXPORT void __kmp_set_teams_thread_limit(int limit); +KMP_EXPORT int __kmp_get_teams_thread_limit(void); /* Lock interface routines (fast versions with gtid passed in) */ KMP_EXPORT void __kmpc_init_lock(ident_t *loc, kmp_int32 gtid, diff --git a/openmp/runtime/src/kmp_ftn_entry.h b/openmp/runtime/src/kmp_ftn_entry.h index 1eb1a0dc9813..cf44019f94be 100644 --- a/openmp/runtime/src/kmp_ftn_entry.h +++ b/openmp/runtime/src/kmp_ftn_entry.h @@ -1373,6 +1373,49 @@ void FTN_STDCALL FTN_FULFILL_EVENT(kmp_event_t *event) { #endif } +// nteams-var per-device ICV +void FTN_STDCALL FTN_SET_NUM_TEAMS(int KMP_DEREF num_teams) { +#ifdef KMP_STUB +// Nothing. +#else + if (!__kmp_init_serial) { + __kmp_serial_initialize(); + } + __kmp_set_num_teams(KMP_DEREF num_teams); +#endif +} +int FTN_STDCALL FTN_GET_MAX_TEAMS(void) { +#ifdef KMP_STUB + return 1; +#else + if (!__kmp_init_serial) { + __kmp_serial_initialize(); + } + return __kmp_get_max_teams(); +#endif +} +// teams-thread-limit-var per-device ICV +void FTN_STDCALL FTN_SET_TEAMS_THREAD_LIMIT(int KMP_DEREF limit) { +#ifdef KMP_STUB +// Nothing. +#else + if (!__kmp_init_serial) { + __kmp_serial_initialize(); + } + __kmp_set_teams_thread_limit(KMP_DEREF limit); +#endif +} +int FTN_STDCALL FTN_GET_TEAMS_THREAD_LIMIT(void) { +#ifdef KMP_STUB + return 1; +#else + if (!__kmp_init_serial) { + __kmp_serial_initialize(); + } + return __kmp_get_teams_thread_limit(); +#endif +} + // display environment variables when requested void FTN_STDCALL FTN_DISPLAY_ENV(int verbose) { #ifndef KMP_STUB diff --git a/openmp/runtime/src/kmp_ftn_os.h b/openmp/runtime/src/kmp_ftn_os.h index 39958e2dbc3a..c122dce47d5d 100644 --- a/openmp/runtime/src/kmp_ftn_os.h +++ b/openmp/runtime/src/kmp_ftn_os.h @@ -135,6 +135,10 @@ #define FTN_GET_SUPPORTED_ACTIVE_LEVELS omp_get_supported_active_levels #define FTN_DISPLAY_ENV omp_display_env #define FTN_FULFILL_EVENT omp_fulfill_event +#define FTN_SET_NUM_TEAMS omp_set_num_teams +#define FTN_GET_MAX_TEAMS omp_get_max_teams +#define FTN_SET_TEAMS_THREAD_LIMIT omp_set_teams_thread_limit +#define FTN_GET_TEAMS_THREAD_LIMIT omp_get_teams_thread_limit #endif /* KMP_FTN_PLAIN */ @@ -259,6 +263,10 @@ #define FTN_GET_SUPPORTED_ACTIVE_LEVELS omp_get_supported_active_levels_ #define FTN_DISPLAY_ENV omp_display_env_ #define FTN_FULFILL_EVENT omp_fulfill_event_ +#define FTN_SET_NUM_TEAMS omp_set_num_teams_ +#define FTN_GET_MAX_TEAMS omp_get_max_teams_ +#define FTN_SET_TEAMS_THREAD_LIMIT omp_set_teams_thread_limit_ +#define FTN_GET_TEAMS_THREAD_LIMIT omp_get_teams_thread_limit_ #endif /* KMP_FTN_APPEND */ @@ -381,6 +389,10 @@ #define FTN_GET_SUPPORTED_ACTIVE_LEVELS OMP_GET_SUPPORTED_ACTIVE_LEVELS #define FTN_DISPLAY_ENV OMP_DISPLAY_ENV #define FTN_FULFILL_EVENT OMP_FULFILL_EVENT +#define FTN_SET_NUM_TEAMS OMP_SET_NUM_TEAMS +#define FTN_GET_MAX_TEAMS OMP_GET_MAX_TEAMS +#define FTN_SET_TEAMS_THREAD_LIMIT OMP_SET_TEAMS_THREAD_LIMIT +#define FTN_GET_TEAMS_THREAD_LIMIT OMP_GET_TEAMS_THREAD_LIMIT #endif /* KMP_FTN_UPPER */ @@ -505,6 +517,10 @@ #define FTN_GET_SUPPORTED_ACTIVE_LEVELS OMP_GET_SUPPORTED_ACTIVE_LEVELS_ #define FTN_DISPLAY_ENV OMP_DISPLAY_ENV_ #define FTN_FULFILL_EVENT OMP_FULFILL_EVENT_ +#define FTN_SET_NUM_TEAMS OMP_SET_NUM_TEAMS_ +#define FTN_GET_MAX_TEAMS OMP_GET_MAX_TEAMS_ +#define FTN_SET_TEAMS_THREAD_LIMIT OMP_SET_TEAMS_THREAD_LIMIT_ +#define FTN_GET_TEAMS_THREAD_LIMIT OMP_GET_TEAMS_THREAD_LIMIT_ #endif /* KMP_FTN_UAPPEND */ diff --git a/openmp/runtime/src/kmp_global.cpp b/openmp/runtime/src/kmp_global.cpp index 0f508e8e7d49..0b6d19a2572c 100644 --- a/openmp/runtime/src/kmp_global.cpp +++ b/openmp/runtime/src/kmp_global.cpp @@ -209,6 +209,8 @@ const char *__kmp_speculative_statsfile = "-"; int __kmp_display_env = FALSE; int __kmp_display_env_verbose = FALSE; int __kmp_omp_cancellation = FALSE; +int __kmp_nteams = 0; +int __kmp_teams_thread_limit = 0; #if KMP_HAVE_MWAIT || KMP_HAVE_UMWAIT int __kmp_user_level_mwait = FALSE; diff --git a/openmp/runtime/src/kmp_runtime.cpp b/openmp/runtime/src/kmp_runtime.cpp index a6e32bd008e1..34e2c223eb0f 100644 --- a/openmp/runtime/src/kmp_runtime.cpp +++ b/openmp/runtime/src/kmp_runtime.cpp @@ -2753,6 +2753,19 @@ int __kmp_get_max_active_levels(int gtid) { return thread->th.th_current_task->td_icvs.max_active_levels; } +// nteams-var per-device ICV +void __kmp_set_num_teams(int num_teams) { + if (num_teams > 0) + __kmp_nteams = num_teams; +} +int __kmp_get_max_teams(void) { return __kmp_nteams; } +// teams-thread-limit-var per-device ICV +void __kmp_set_teams_thread_limit(int limit) { + if (limit > 0) + __kmp_teams_thread_limit = limit; +} +int __kmp_get_teams_thread_limit(void) { return __kmp_teams_thread_limit; } + KMP_BUILD_ASSERT(sizeof(kmp_sched_t) == sizeof(int)); KMP_BUILD_ASSERT(sizeof(enum sched_type) == sizeof(int)); @@ -7420,8 +7433,13 @@ void __kmp_push_num_teams(ident_t *id, int gtid, int num_teams, KMP_DEBUG_ASSERT(num_teams >= 0); KMP_DEBUG_ASSERT(num_threads >= 0); - if (num_teams == 0) - num_teams = 1; // default number of teams is 1. + if (num_teams == 0) { + if (__kmp_nteams > 0) { + num_teams = __kmp_nteams; + } else { + num_teams = 1; // default number of teams is 1. + } + } if (num_teams > __kmp_teams_max_nth) { // if too many teams requested? if (!__kmp_reserve_warn) { __kmp_reserve_warn = 1; @@ -7441,7 +7459,11 @@ void __kmp_push_num_teams(ident_t *id, int gtid, int num_teams, KMP_DEBUG_ASSERT(__kmp_avail_proc); KMP_DEBUG_ASSERT(__kmp_dflt_team_nth); if (num_threads == 0) { - num_threads = __kmp_avail_proc / num_teams; + if (__kmp_teams_thread_limit > 0) { + num_threads = __kmp_teams_thread_limit; + } else { + num_threads = __kmp_avail_proc / num_teams; + } // adjust num_threads w/o warning as it is not user setting // num_threads = min(num_threads, nthreads-var, thread-limit-var) // no thread_limit clause specified - do not change thread-limit-var ICV diff --git a/openmp/runtime/src/kmp_settings.cpp b/openmp/runtime/src/kmp_settings.cpp index b7d5d3b0d689..b711813d9c96 100644 --- a/openmp/runtime/src/kmp_settings.cpp +++ b/openmp/runtime/src/kmp_settings.cpp @@ -633,6 +633,33 @@ static void __kmp_stg_print_thread_limit(kmp_str_buf_t *buffer, __kmp_stg_print_int(buffer, name, __kmp_cg_max_nth); } // __kmp_stg_print_thread_limit +// ----------------------------------------------------------------------------- +// OMP_NUM_TEAMS +static void __kmp_stg_parse_nteams(char const *name, char const *value, + void *data) { + __kmp_stg_parse_int(name, value, 1, __kmp_sys_max_nth, &__kmp_nteams); + K_DIAG(1, ("__kmp_nteams == %d\n", __kmp_nteams)); +} // __kmp_stg_parse_nteams + +static void __kmp_stg_print_nteams(kmp_str_buf_t *buffer, char const *name, + void *data) { + __kmp_stg_print_int(buffer, name, __kmp_nteams); +} // __kmp_stg_print_nteams + +// ----------------------------------------------------------------------------- +// OMP_TEAMS_THREAD_LIMIT +static void __kmp_stg_parse_teams_th_limit(char const *name, char const *value, + void *data) { + __kmp_stg_parse_int(name, value, 1, __kmp_sys_max_nth, + &__kmp_teams_thread_limit); + K_DIAG(1, ("__kmp_teams_thread_limit == %d\n", __kmp_teams_thread_limit)); +} // __kmp_stg_parse_teams_th_limit + +static void __kmp_stg_print_teams_th_limit(kmp_str_buf_t *buffer, + char const *name, void *data) { + __kmp_stg_print_int(buffer, name, __kmp_teams_thread_limit); +} // __kmp_stg_print_teams_th_limit + // ----------------------------------------------------------------------------- // KMP_TEAMS_THREAD_LIMIT static void __kmp_stg_parse_teams_thread_limit(char const *name, @@ -5114,6 +5141,10 @@ static kmp_setting_t __kmp_stg_table[] = { __kmp_stg_print_thread_limit, NULL, 0, 0}, {"KMP_TEAMS_THREAD_LIMIT", __kmp_stg_parse_teams_thread_limit, __kmp_stg_print_teams_thread_limit, NULL, 0, 0}, + {"OMP_NUM_TEAMS", __kmp_stg_parse_nteams, __kmp_stg_print_nteams, NULL, 0, + 0}, + {"OMP_TEAMS_THREAD_LIMIT", __kmp_stg_parse_teams_th_limit, + __kmp_stg_print_teams_th_limit, NULL, 0, 0}, {"OMP_WAIT_POLICY", __kmp_stg_parse_wait_policy, __kmp_stg_print_wait_policy, NULL, 0, 0}, {"KMP_DISP_NUM_BUFFERS", __kmp_stg_parse_disp_buffers, diff --git a/openmp/runtime/test/api/omp_nteams_api.c b/openmp/runtime/test/api/omp_nteams_api.c new file mode 100644 index 000000000000..10e92517c604 --- /dev/null +++ b/openmp/runtime/test/api/omp_nteams_api.c @@ -0,0 +1,26 @@ +// RUN: %libomp-compile-and-run + +#include +#include +#include + +int main(int argc, char** argv) +{ + int iset, iget; + iset = 5; + omp_set_num_teams(iset); + iget = omp_get_max_teams(); + if (iset != iget) { + fprintf(stderr, "error: nteams-var set to %d, getter returned %d\n", iset, iget); + exit(1); + } + iset = 7; + omp_set_teams_thread_limit(iset); + iget = omp_get_teams_thread_limit(); + if (iset != iget) { + fprintf(stderr, "error: teams-thread-limit-var set to %d, getter returned %d\n", iset, iget); + exit(1); + } + printf("passed\n"); + return 0; +} diff --git a/openmp/runtime/test/api/omp_nteams_api_env.c b/openmp/runtime/test/api/omp_nteams_api_env.c new file mode 100644 index 000000000000..d11c6bfb60a4 --- /dev/null +++ b/openmp/runtime/test/api/omp_nteams_api_env.c @@ -0,0 +1,24 @@ +// RUN: %libomp-compile && env OMP_NUM_TEAMS=5 OMP_TEAMS_THREAD_LIMIT=7 %libomp-run + +#include +#include +#include + +int main(int argc, char** argv) +{ + int iset, iget; + iset = 5; + iget = omp_get_max_teams(); + if (iset != iget) { + fprintf(stderr, "error: nteams-var set to %d, getter returned %d\n", iset, iget); + exit(1); + } + iset = 7; + iget = omp_get_teams_thread_limit(); + if (iset != iget) { + fprintf(stderr, "error: teams-thread-limit-var set to %d, getter returned %d\n", iset, iget); + exit(1); + } + printf("passed\n"); + return 0; +} diff --git a/openmp/runtime/test/api/omp_nteams_api_env2.c b/openmp/runtime/test/api/omp_nteams_api_env2.c new file mode 100644 index 000000000000..486380395359 --- /dev/null +++ b/openmp/runtime/test/api/omp_nteams_api_env2.c @@ -0,0 +1,26 @@ +// RUN: %libomp-compile && env OMP_NUM_TEAMS=5 OMP_TEAMS_THREAD_LIMIT=7 %libomp-run + +#include +#include +#include + +int main(int argc, char** argv) +{ + int iset, iget; + iset = 4; // should override OMP_NUM_TEAMS=5 + omp_set_num_teams(iset); + iget = omp_get_max_teams(); + if (iset != iget) { + fprintf(stderr, "error: nteams-var set to %d, getter returned %d\n", iset, iget); + exit(1); + } + iset = 6; // should override OMP_TEAMS_THREAD_LIMIT=7 + omp_set_teams_thread_limit(iset); + iget = omp_get_teams_thread_limit(); + if (iset != iget) { + fprintf(stderr, "error: teams-thread-limit-var set to %d, getter returned %d\n", iset, iget); + exit(1); + } + printf("passed\n"); + return 0; +}