Skip to content

Commit

Permalink
Introduce GOMP_taskloop API
Browse files Browse the repository at this point in the history
This patch introduces GOMP_taskloop to our API. It adds GOMP_4.5 to our
version symbols. Being a wrapper around __kmpc_taskloop, the function
creates a task with the loop bounds properly nested in the shareds so that
the GOMP task thunk will work properly. Also, the firstprivate copy constructors
are properly handled using the __kmp_gomp_task_dup() auxiliary function.

Currently, only linear spawning of tasks is supported
for the GOMP_taskloop interface.

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

llvm-svn: 330282
  • Loading branch information
jpeyton52 committed Apr 18, 2018
1 parent 099c720 commit 27a677f
Show file tree
Hide file tree
Showing 9 changed files with 297 additions and 22 deletions.
2 changes: 2 additions & 0 deletions openmp/runtime/src/exports_so.txt
Expand Up @@ -117,5 +117,7 @@ GOMP_3.0 {
} GOMP_2.0;
GOMP_4.0 {
} GOMP_3.0;
GOMP_4.5 {
} GOMP_4.0;

# end of file #
8 changes: 8 additions & 0 deletions openmp/runtime/src/kmp.h
Expand Up @@ -2261,8 +2261,16 @@ struct kmp_taskdata { /* aligned during dynamic allocation */
#if OMP_45_ENABLED
kmp_task_team_t *td_task_team;
kmp_int32 td_size_alloc; // The size of task structure, including shareds etc.
#if defined(KMP_GOMP_COMPAT)
// 4 or 8 byte integers for the loop bounds in GOMP_taskloop
kmp_int32 td_size_loop_bounds;
#endif
#endif // OMP_45_ENABLED
kmp_taskdata_t *td_last_tied; // keep tied task for task scheduling constraint
#if defined(KMP_GOMP_COMPAT) && OMP_45_ENABLED
// GOMP sends in a copy function for copy constructors
void (*td_copy_func)(void *, void *);
#endif
#if OMPT_SUPPORT
ompt_task_info_t ompt_task_info;
#endif
Expand Down
4 changes: 4 additions & 0 deletions openmp/runtime/src/kmp_ftn_os.h
Expand Up @@ -613,4 +613,8 @@
#define KMP_API_NAME_GOMP_TARGET_UPDATE GOMP_target_update
#define KMP_API_NAME_GOMP_TEAMS GOMP_teams

// All GOMP_4.5 symbols
#define KMP_API_NAME_GOMP_TASKLOOP GOMP_taskloop
#define KMP_API_NAME_GOMP_TASKLOOP_ULL GOMP_taskloop_ull

#endif /* KMP_FTN_OS_H */
136 changes: 136 additions & 0 deletions openmp/runtime/src/kmp_gsupport.cpp
Expand Up @@ -1413,6 +1413,137 @@ void KMP_EXPAND_NAME(KMP_API_NAME_GOMP_TEAMS)(unsigned int num_teams,
}
#endif // OMP_40_ENABLED

#if OMP_45_ENABLED

// Task duplication function which copies src to dest (both are
// preallocated task structures)
static void __kmp_gomp_task_dup(kmp_task_t *dest, kmp_task_t *src,
kmp_int32 last_private) {
kmp_taskdata_t *taskdata = KMP_TASK_TO_TASKDATA(src);
if (taskdata->td_copy_func) {
(taskdata->td_copy_func)(dest->shareds, src->shareds);
}
}

#ifdef __cplusplus
} // extern "C"
#endif

template <typename T>
void __GOMP_taskloop(void (*func)(void *), void *data,
void (*copy_func)(void *, void *), long arg_size,
long arg_align, unsigned gomp_flags,
unsigned long num_tasks, int priority, T start, T end,
T step) {
typedef void (*p_task_dup_t)(kmp_task_t *, kmp_task_t *, kmp_int32);
MKLOC(loc, "GOMP_taskloop");
int sched;
T *loop_bounds;
int gtid = __kmp_entry_gtid();
kmp_int32 flags = 0;
int if_val = gomp_flags & (1u << 10);
int nogroup = gomp_flags & (1u << 11);
int up = gomp_flags & (1u << 8);
p_task_dup_t task_dup = NULL;
kmp_tasking_flags_t *input_flags = (kmp_tasking_flags_t *)&flags;
#ifdef KMP_DEBUG
{
const char *buff;
buff = __kmp_str_format(
"GOMP_taskloop: T#%%d: func:%%p data:%%p copy_func:%%p "
"arg_size:%%ld arg_align:%%ld gomp_flags:0x%%x num_tasks:%%lu "
"priority:%%d start:%%%s end:%%%s step:%%%s\n",
traits_t<T>::spec, traits_t<T>::spec, traits_t<T>::spec);
KA_TRACE(20, (buff, gtid, func, data, copy_func, arg_size, arg_align,
gomp_flags, num_tasks, priority, start, end, step));
__kmp_str_free(&buff);
}
#endif
KMP_ASSERT((size_t)arg_size >= 2 * sizeof(T));
KMP_ASSERT(arg_align > 0);
// The low-order bit is the "untied" flag
if (!(gomp_flags & 1)) {
input_flags->tiedness = 1;
}
// The second low-order bit is the "final" flag
if (gomp_flags & 2) {
input_flags->final = 1;
}
// Negative step flag
if (!up) {
// If step is flagged as negative, but isn't properly sign extended
// Then manually sign extend it. Could be a short, int, char embedded
// in a long. So cannot assume any cast.
if (step > 0) {
for (int i = sizeof(T) * CHAR_BIT - 1; i >= 0L; --i) {
// break at the first 1 bit
if (step & ((T)1 << i))
break;
step |= ((T)1 << i);
}
}
}
input_flags->native = 1;
// Figure out if none/grainsize/num_tasks clause specified
if (num_tasks > 0) {
if (gomp_flags & (1u << 9))
sched = 1; // grainsize specified
else
sched = 2; // num_tasks specified
// neither grainsize nor num_tasks specified
} else {
sched = 0;
}

// __kmp_task_alloc() sets up all other flags
kmp_task_t *task =
__kmp_task_alloc(&loc, gtid, input_flags, sizeof(kmp_task_t),
arg_size + arg_align - 1, (kmp_routine_entry_t)func);
kmp_taskdata_t *taskdata = KMP_TASK_TO_TASKDATA(task);
taskdata->td_copy_func = copy_func;
taskdata->td_size_loop_bounds = sizeof(T);

// re-align shareds if needed and setup firstprivate copy constructors
// through the task_dup mechanism
task->shareds = (void *)((((size_t)task->shareds) + arg_align - 1) /
arg_align * arg_align);
if (copy_func) {
task_dup = __kmp_gomp_task_dup;
}
KMP_MEMCPY(task->shareds, data, arg_size);

loop_bounds = (T *)task->shareds;
loop_bounds[0] = start;
loop_bounds[1] = end + (up ? -1 : 1);
__kmpc_taskloop(&loc, gtid, task, if_val, (kmp_uint64 *)&(loop_bounds[0]),
(kmp_uint64 *)&(loop_bounds[1]), (kmp_int64)step, nogroup,
sched, (kmp_uint64)num_tasks, (void *)task_dup);
}

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

void KMP_EXPAND_NAME(KMP_API_NAME_GOMP_TASKLOOP)(
void (*func)(void *), void *data, void (*copy_func)(void *, void *),
long arg_size, long arg_align, unsigned gomp_flags, unsigned long num_tasks,
int priority, long start, long end, long step) {
__GOMP_taskloop<long>(func, data, copy_func, arg_size, arg_align, gomp_flags,
num_tasks, priority, start, end, step);
}

void KMP_EXPAND_NAME(KMP_API_NAME_GOMP_TASKLOOP_ULL)(
void (*func)(void *), void *data, void (*copy_func)(void *, void *),
long arg_size, long arg_align, unsigned gomp_flags, unsigned long num_tasks,
int priority, unsigned long long start, unsigned long long end,
unsigned long long step) {
__GOMP_taskloop<unsigned long long>(func, data, copy_func, arg_size,
arg_align, gomp_flags, num_tasks,
priority, start, end, step);
}

#endif

/* The following sections of code create aliases for the GOMP_* functions, then
create versioned symbols using the assembler directive .symver. This is only
pertinent for ELF .so library. The KMP_VERSION_SYMBOL macro is defined in
Expand Down Expand Up @@ -1521,6 +1652,11 @@ KMP_VERSION_SYMBOL(KMP_API_NAME_GOMP_TARGET_UPDATE, 40, "GOMP_4.0");
KMP_VERSION_SYMBOL(KMP_API_NAME_GOMP_TEAMS, 40, "GOMP_4.0");
#endif

#if OMP_45_ENABLED
KMP_VERSION_SYMBOL(KMP_API_NAME_GOMP_TASKLOOP, 45, "GOMP_4.5");
KMP_VERSION_SYMBOL(KMP_API_NAME_GOMP_TASKLOOP_ULL, 45, "GOMP_4.5");
#endif

#endif // KMP_USE_VERSION_SYMBOLS

#ifdef __cplusplus
Expand Down
8 changes: 8 additions & 0 deletions openmp/runtime/src/kmp_os.h
Expand Up @@ -209,6 +209,14 @@ template <> struct traits_t<unsigned int> {
static const unsigned_t min_value = 0x00000000;
static const int type_size = sizeof(unsigned_t);
};
// long
template <> struct traits_t<signed long> {
typedef signed long signed_t;
typedef unsigned long unsigned_t;
typedef long double floating_t;
static char const *spec;
static const int type_size = sizeof(signed_t);
};
// long long
template <> struct traits_t<signed long long> {
typedef signed long long signed_t;
Expand Down
1 change: 1 addition & 0 deletions openmp/runtime/src/kmp_sched.cpp
Expand Up @@ -35,6 +35,7 @@ char const *traits_t<int>::spec = "d";
char const *traits_t<unsigned int>::spec = "u";
char const *traits_t<long long>::spec = "lld";
char const *traits_t<unsigned long long>::spec = "llu";
char const *traits_t<long>::spec = "ld";
//-------------------------------------------------------------------------
#endif

Expand Down

0 comments on commit 27a677f

Please sign in to comment.