From 41c573230c67d06e1bced5c86b2d266e1a4a7869 Mon Sep 17 00:00:00 2001 From: Thilina Rathnayake Date: Wed, 4 Oct 2023 16:43:31 -0400 Subject: [PATCH 1/5] Rename a few python functions --- include/nomp-loopy.h | 13 ++++++------- src/loopy.c | 13 ++++++------- src/nomp.c | 9 ++++----- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/include/nomp-loopy.h b/include/nomp-loopy.h index 585ea3b1..684f0571 100644 --- a/include/nomp-loopy.h +++ b/include/nomp-loopy.h @@ -26,23 +26,22 @@ int nomp_py_realize_reduction(PyObject **knl, const char *var, int nomp_py_set_annotate_func(PyObject **func, const char *path); -int nomp_py_apply_annotations(PyObject **kernel, PyObject *function, - const PyObject *annotations, - const PyObject *context); +int nomp_py_annotate(PyObject **kernel, PyObject *function, + const PyObject *annotations, const PyObject *context); -int nomp_py_apply_transform(PyObject **knl, const char *file, const char *func, - const PyObject *context); +int nomp_py_transform(PyObject **knl, const char *file, const char *func, + const PyObject *context); int nomp_py_get_knl_name_and_src(char **name, char **src, const PyObject *knl); int nomp_py_get_grid_size(nomp_prog_t *prg, PyObject *knl); +void nomp_py_get_str(const char *msg, PyObject *obj); + int nomp_symengine_eval_grid_size(nomp_prog_t *prg); int nomp_symengine_update(CMapBasicBasic *map, const char *key, const long val); -void nomp_py_print(const char *msg, PyObject *obj); - #ifdef __cplusplus } #endif diff --git a/src/loopy.c b/src/loopy.c index 2ca4fa5a..8039e085 100644 --- a/src/loopy.c +++ b/src/loopy.c @@ -20,7 +20,7 @@ static char backend[NOMP_MAX_BUFFER_SIZE + 1]; * @param obj Python object to be printed. * @return void */ -void nomp_py_print(const char *const message, PyObject *const obj) { +void nomp_py_get_str(const char *const message, PyObject *const obj) { PyObject *py_repr = PyObject_Repr(obj); PyObject *py_str = PyUnicode_AsEncodedString(py_repr, "utf-8", "~E~"); const char *str = PyBytes_AS_STRING(py_str); @@ -305,9 +305,9 @@ int nomp_py_get_knl_name_and_src(char **name, char **src, * as backend, device details, etc. * @return int */ -int nomp_py_apply_annotations(PyObject **kernel, PyObject *const function, - const PyObject *const annotations, - const PyObject *const context) { +int nomp_py_annotate(PyObject **kernel, PyObject *const function, + const PyObject *const annotations, + const PyObject *const context) { if (!kernel || !*kernel || !function) return 0; @@ -341,9 +341,8 @@ int nomp_py_apply_annotations(PyObject **kernel, PyObject *const function, * information such as backend, device details, etc. * @return int */ -int nomp_py_apply_transform(PyObject **kernel, const char *const file, - const char *function, - const PyObject *const context) { +int nomp_py_transform(PyObject **kernel, const char *const file, + const char *function, const PyObject *const context) { // If either kernel, file, or function are NULL, we don't have to do anything: if (kernel == NULL || *kernel == NULL || file == NULL || function == NULL) return 0; diff --git a/src/nomp.c b/src/nomp.c index b2eadae4..46357ce4 100644 --- a/src/nomp.c +++ b/src/nomp.c @@ -78,7 +78,7 @@ static inline int nomp_check_cmd_line(nomp_config_t *const cfg, unsigned argc, strncpy(cfg->scripts_dir, argv[i], PATH_MAX), valid = 1; if (!valid) { - nomp_log(0, NOMP_WARNING, "Unknown command line argument: %s.", + nomp_log(NOMP_SUCCESS, NOMP_WARNING, "Unknown command line argument: %s.", argv[i - 1]); } @@ -239,7 +239,7 @@ int nomp_init(int argc, const char **argv) { initialized = 1; - nomp_log(0, NOMP_INFO, "libnomp initialized successfully."); + nomp_log(NOMP_SUCCESS, NOMP_INFO, "libnomp initialized successfully."); return 0; } @@ -504,12 +504,11 @@ int nomp_jit(int *id, const char *csrc, const char **clauses, int nargs, ...) { nomp_check(nomp_py_c_to_loopy(&knl, csrc)); // Handle annotate clauses if they exist. - nomp_check(nomp_py_apply_annotations(&knl, nomp.py_annotate, m.dict, - nomp.py_context)); + nomp_check(nomp_py_annotate(&knl, nomp.py_annotate, m.dict, nomp.py_context)); Py_XDECREF(m.dict); // Handle transform clauses. - nomp_check(nomp_py_apply_transform(&knl, m.file, m.func, nomp.py_context)); + nomp_check(nomp_py_transform(&knl, m.file, m.func, nomp.py_context)); nomp_free(&m.file), nomp_free(&m.func); // Handle reductions if they exist. From 0146bea26542646e9cb0ee48cfb2107bcc4eeee2 Mon Sep 17 00:00:00 2001 From: Thilina Rathnayake Date: Wed, 4 Oct 2023 17:18:03 -0400 Subject: [PATCH 2/5] Get rid of `struct nomp_meta_t` --- src/nomp.c | 117 ++++++++++++++++++----------------------------------- 1 file changed, 40 insertions(+), 77 deletions(-) diff --git a/src/nomp.c b/src/nomp.c index 46357ce4..67b4a773 100644 --- a/src/nomp.c +++ b/src/nomp.c @@ -145,24 +145,25 @@ static inline int deallocate_scratch_memory(nomp_backend_t *bnd) { return 0; } -static inline int init_backend(nomp_backend_t *const bnd, +static inline int init_backend(nomp_backend_t *const backend, const nomp_config_t *const cfg) { - bnd->py_context = PyDict_New(); - PyObject *obj = PyUnicode_FromString(cfg->backend); - PyDict_SetItemString(bnd->py_context, "backend::name", obj); - Py_XDECREF(obj); + backend->py_context = PyDict_New(); + + PyObject *py_str_backend = PyUnicode_FromString(cfg->backend); + PyDict_SetItemString(backend->py_context, "backend::name", py_str_backend); + Py_XDECREF(py_str_backend); if (strncmp(cfg->backend, "opencl", NOMP_MAX_BUFFER_SIZE) == 0) { #if defined(OPENCL_ENABLED) - nomp_check(opencl_init(bnd, cfg->platform, cfg->device)); + nomp_check(opencl_init(backend, cfg->platform, cfg->device)); #endif } else if (strncmp(cfg->backend, "cuda", NOMP_MAX_BUFFER_SIZE) == 0) { #if defined(CUDA_ENABLED) - nomp_check(cuda_init(bnd, cfg->platform, cfg->device)); + nomp_check(cuda_init(backend, cfg->platform, cfg->device)); #endif } else if (strncmp(cfg->backend, "hip", NOMP_MAX_BUFFER_SIZE) == 0) { #if defined(HIP_ENABLED) - nomp_check(hip_init(bnd, cfg->platform, cfg->device)); + nomp_check(hip_init(backend, cfg->platform, cfg->device)); #endif } else { return nomp_log(NOMP_USER_INPUT_IS_INVALID, NOMP_ERROR, @@ -355,72 +356,43 @@ static nomp_prog_t **progs = NULL; static unsigned progs_n = 0; static unsigned progs_max = 0; -struct nomp_meta_t { - char *file, *func; - PyObject *dict; -}; - -static int parse_clauses(struct nomp_meta_t *meta, nomp_prog_t *prg, - const char **clauses) { - // Currently, we only support `transform` and - // `annotate` and `jit`. - meta->dict = PyDict_New(), meta->file = meta->func = NULL; +static int act_on_clases(PyObject **kernel, nomp_prog_t *program, + const char **const clauses, + const nomp_backend_t *const backend) { + // Currently, we only support `transform` and `reduce` clauses. unsigned i = 0; while (clauses[i]) { if (strncmp(clauses[i], "transform", NOMP_MAX_BUFFER_SIZE) == 0) { - nomp_check(nomp_py_check_module((const char *)clauses[i + 1], - (const char *)clauses[i + 2])); - meta->file = strndup(clauses[i + 1], PATH_MAX); - meta->func = strndup(clauses[i + 2], NOMP_MAX_BUFFER_SIZE); - i += 3; - } else if (strncmp(clauses[i], "annotate", NOMP_MAX_BUFFER_SIZE) == 0) { - if (clauses[i + 1] == NULL || clauses[i + 2] == NULL) { - return nomp_log(NOMP_USER_INPUT_IS_INVALID, NOMP_ERROR, - "\"annotate\" clause should be followed by " - "a key value " - "pair. At least one of them is not " - "provided."); - } - const char *key = clauses[i + 1], *val = clauses[i + 2]; - PyObject *pkey = - PyUnicode_FromStringAndSize(key, strnlen(key, NOMP_MAX_BUFFER_SIZE)); - PyObject *pval = - PyUnicode_FromStringAndSize(val, strnlen(val, NOMP_MAX_BUFFER_SIZE)); - PyDict_SetItem(meta->dict, pkey, pval); - Py_XDECREF(pkey), Py_XDECREF(pval); + const char *file = clauses[i + 1], *function = clauses[i + 2]; + nomp_check(nomp_py_check_module(file, function)); + nomp_check( + nomp_py_transform(kernel, file, function, backend->py_context)); i += 3; - } else if (strncmp(clauses[i], "reduce", NOMP_MAX_BUFFER_SIZE) == 0) { - if (clauses[i + 1] == NULL || clauses[i + 2] == NULL) { - return nomp_log(NOMP_USER_INPUT_IS_INVALID, NOMP_ERROR, - "\"reduce\" clause should be followed by a " - "variable name and an " - "operation. At least one of them is not " - "provided."); - } - for (unsigned j = 0; j < prg->nargs; j++) { - if (strncmp(prg->args[j].name, clauses[i + 1], NOMP_MAX_BUFFER_SIZE) == - 0) { - prg->redn_type = prg->args[j].type, prg->args[j].type = NOMP_PTR; - prg->redn_size = prg->args[j].size, prg->redn_idx = j; + continue; + } + + if (strncmp(clauses[i], "reduce", NOMP_MAX_BUFFER_SIZE) == 0) { + for (unsigned j = 0; j < program->nargs; j++) { + if (strncmp(program->args[j].name, clauses[i + 1], + NOMP_MAX_BUFFER_SIZE) == 0) { + program->redn_type = program->args[j].type; + program->redn_size = program->args[j].size; + program->redn_idx = j; + program->args[j].type = NOMP_PTR; break; } } if (strncmp(clauses[i + 2], "+", 2) == 0) - prg->redn_op = NOMP_SUM; - else if (strncmp(clauses[i + 2], "*", 2) == 0) - prg->redn_op = NOMP_PROD; + program->redn_op = NOMP_SUM; + if (strncmp(clauses[i + 2], "*", 2) == 0) + program->redn_op = NOMP_PROD; i += 3; - } else if (strncmp(clauses[i], "pin", NOMP_MAX_BUFFER_SIZE) == 0) { - // Check if we have to use pinned memory. - return nomp_log(NOMP_NOT_IMPLEMENTED_ERROR, NOMP_ERROR, - "Pinned memory support is " - "not yet implemented."); - } else { - return nomp_log(NOMP_USER_INPUT_IS_INVALID, NOMP_ERROR, - "Clause \"%s\" passed into nomp_jit is not a " - "valid clause.", - clauses[i]); + continue; } + + return nomp_log(NOMP_USER_INPUT_IS_INVALID, NOMP_ERROR, + "Clause \"%s\" passed into nomp_jit is not a valid clause.", + clauses[i]); } return 0; @@ -429,7 +401,8 @@ static int parse_clauses(struct nomp_meta_t *meta, nomp_prog_t *prg, static inline nomp_prog_t *init_args(int progs_n, int nargs, va_list args) { nomp_prog_t *prg = progs[progs_n] = nomp_calloc(nomp_prog_t, 1); prg->args = nomp_calloc(nomp_arg_t, nargs); - prg->nargs = nargs, prg->redn_idx = -1; + prg->nargs = nargs; + prg->redn_idx = -1; prg->map = mapbasicbasic_new(); prg->sym_global = vecbasic_new(), prg->sym_local = vecbasic_new(); @@ -494,22 +467,12 @@ int nomp_jit(int *id, const char *csrc, const char **clauses, int nargs, ...) { nomp_prog_t *prg = init_args(progs_n, nargs, args); va_end(args); - // Parse the clauses to find transformations file, function and other - // annotations. Annotations are returned as a Python dictionary. - struct nomp_meta_t m; - nomp_check(parse_clauses(&m, prg, clauses)); - // Create loopy kernel from C source. PyObject *knl = NULL; nomp_check(nomp_py_c_to_loopy(&knl, csrc)); - // Handle annotate clauses if they exist. - nomp_check(nomp_py_annotate(&knl, nomp.py_annotate, m.dict, nomp.py_context)); - Py_XDECREF(m.dict); - - // Handle transform clauses. - nomp_check(nomp_py_transform(&knl, m.file, m.func, nomp.py_context)); - nomp_free(&m.file), nomp_free(&m.func); + // Act on the clauses: transform, reduce, etc. and get the kernel + nomp_check(act_on_clases(&knl, prg, clauses, &nomp)); // Handle reductions if they exist. if (prg->redn_idx >= 0) From 9729a8666ff26e5d63e61f81e0d30d3f84fb05f3 Mon Sep 17 00:00:00 2001 From: Thilina Rathnayake Date: Wed, 4 Oct 2023 22:28:36 -0400 Subject: [PATCH 3/5] Add a poor man's function call trace --- include/nomp-impl.h | 1 + src/nomp.c | 10 ++++------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/include/nomp-impl.h b/include/nomp-impl.h index e0abbcb2..f5245efe 100644 --- a/include/nomp-impl.h +++ b/include/nomp-impl.h @@ -295,6 +295,7 @@ extern "C" { int err_ = (err); \ if (err_ > 0) \ return err_; \ + nomp_log(NOMP_SUCCESS, NOMP_INFO, "OK. Function: %s", __func__); \ } #define NOMP_MEM_OFFSET(start, usize) ((start) * (usize)) diff --git a/src/nomp.c b/src/nomp.c index 67b4a773..b1dcbf10 100644 --- a/src/nomp.c +++ b/src/nomp.c @@ -240,8 +240,6 @@ int nomp_init(int argc, const char **argv) { initialized = 1; - nomp_log(NOMP_SUCCESS, NOMP_INFO, "libnomp initialized successfully."); - return 0; } @@ -356,9 +354,9 @@ static nomp_prog_t **progs = NULL; static unsigned progs_n = 0; static unsigned progs_max = 0; -static int act_on_clases(PyObject **kernel, nomp_prog_t *program, - const char **const clauses, - const nomp_backend_t *const backend) { +static int act_on_clauses(PyObject **kernel, nomp_prog_t *program, + const char **const clauses, + const nomp_backend_t *const backend) { // Currently, we only support `transform` and `reduce` clauses. unsigned i = 0; while (clauses[i]) { @@ -472,7 +470,7 @@ int nomp_jit(int *id, const char *csrc, const char **clauses, int nargs, ...) { nomp_check(nomp_py_c_to_loopy(&knl, csrc)); // Act on the clauses: transform, reduce, etc. and get the kernel - nomp_check(act_on_clases(&knl, prg, clauses, &nomp)); + nomp_check(act_on_clauses(&knl, prg, clauses, &nomp)); // Handle reductions if they exist. if (prg->redn_idx >= 0) From f5ee658871115d6a1c83f23ef2fa819c54574a15 Mon Sep 17 00:00:00 2001 From: Thilina Rathnayake Date: Wed, 4 Oct 2023 22:29:04 -0400 Subject: [PATCH 4/5] Refactor nomp_update() --- src/nomp.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/nomp.c b/src/nomp.c index b1dcbf10..3af2b154 100644 --- a/src/nomp.c +++ b/src/nomp.c @@ -281,20 +281,22 @@ static unsigned mem_if_exist(void *p, size_t idx0, size_t idx1, size_t usize) { /** * @ingroup nomp_user_api - * @brief Performs device to host (D2H) and host to device (H2D) memory - * transfers, allocating and freeing of memory in the device. * - * @param[in] ptr Pointer to the host memory location. - * @param[in] idx0 Start index in the vector to start copying. - * @param[in] idx1 End index in the vector to end the copying. - * @param[in] usize Size of a single vector element. - * @param[in] op Operation to perform (One of #nomp_map_direction_t). - * @return int + * @brief libnomp function for managing device memory. This can be used to + * performs device to host (D2H) and host to device (H2D) memory + * transfers, device memory allocation and release. * * @details Operation \p op will be performed on the array slice [\p start_idx, * \p end_idx), i.e., on array elements start_idx, ... end_idx - 1. This method * returns a non-zero value if there is an error and 0 otherwise. * + * @param[in] ptr Pointer to host memory location (start of host memory array). + * @param[in] idx0 Start index in the \p ptr to start copying. + * @param[in] idx1 End index in the \p ptr to end the copying. + * @param[in] unit_size Size of a single element in the array \p ptr. + * @param[in] op Operation to perform (One of ::nomp_map_direction_t). + * @return int + * * Example usage: * @code{.c} * int N = 10; @@ -316,9 +318,9 @@ static unsigned mem_if_exist(void *p, size_t idx0, size_t idx1, size_t usize) { * * @endcode */ -int nomp_update(void *ptr, size_t idx0, size_t idx1, size_t usize, +int nomp_update(void *ptr, size_t idx0, size_t idx1, size_t unit_size, nomp_map_direction_t op) { - unsigned idx = mem_if_exist(ptr, idx0, idx1, usize); + unsigned idx = mem_if_exist(ptr, idx0, idx1, unit_size); if (idx == mems_n) { // A new entry can't be created with NOMP_FREE or // NOMP_FROM. @@ -334,11 +336,11 @@ int nomp_update(void *ptr, size_t idx0, size_t idx1, size_t usize, mems = nomp_realloc(mems, nomp_mem_t *, mems_max); } nomp_mem_t *m = mems[mems_n] = nomp_calloc(nomp_mem_t, 1); - m->idx0 = idx0, m->idx1 = idx1, m->usize = usize; + m->idx0 = idx0, m->idx1 = idx1, m->usize = unit_size; m->hptr = ptr, m->bptr = NULL; } - nomp_check(nomp.update(&nomp, mems[idx], op, idx0, idx1, usize)); + nomp_check(nomp.update(&nomp, mems[idx], op, idx0, idx1, unit_size)); // Device memory object was released. if (mems[idx]->bptr == NULL) @@ -415,6 +417,7 @@ static inline nomp_prog_t *init_args(int progs_n, int nargs, va_list args) { /** * @ingroup nomp_user_api + * * @brief Generate and compile a kernel for the target backend (OpenCL, etc.) * from C source. * From 9584d034e138409eb31c92a6f2a96f57b2ea6175 Mon Sep 17 00:00:00 2001 From: Thilina Rathnayake Date: Wed, 4 Oct 2023 22:53:50 -0400 Subject: [PATCH 5/5] Remove :content-only: from docs --- docs/internal-api.rst | 25 ++++++++++--------------- docs/user-api.rst | 6 ------ include/nomp-impl.h | 2 +- include/nomp.h | 3 ++- 4 files changed, 13 insertions(+), 23 deletions(-) diff --git a/docs/internal-api.rst b/docs/internal-api.rst index 0a69b2c4..a23e9369 100644 --- a/docs/internal-api.rst +++ b/docs/internal-api.rst @@ -8,59 +8,54 @@ Internal API Internal Types ^^^^^^^^^^^^^^ - -Below is a list of internal types (structures and enums) used internally by -libnomp. - .. doxygengroup:: nomp_internal_types :project: libnomp - :content-only: :members: -Helper Macros -^^^^^^^^^^^^^ +Internal Macros +^^^^^^^^^^^^^^^ .. doxygengroup:: nomp_internal_macros :project: libnomp - :content-only: + :members: Memory Management Functions and Macros ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. doxygengroup:: nomp_mem_utils :project: libnomp - :content-only: + :members: Backend Initialization Functions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. doxygengroup:: nomp_backend_init :project: libnomp - :content-only: + :members: Python Helper Functions ^^^^^^^^^^^^^^^^^^^^^^^^ .. doxygengroup:: nomp_py_utils :project: libnomp - :content-only: + :members: Reductions and Related Functions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. doxygengroup:: nomp_reduction_utils :project: libnomp - :content-only: + :members: Logging Functions ^^^^^^^^^^^^^^^^^ .. doxygengroup:: nomp_log_utils :project: libnomp - :content-only: + :members: Profiling Functions ^^^^^^^^^^^^^^^^^^^ .. doxygengroup:: nomp_profiler_utils :project: libnomp - :content-only: + :members: Other helper Functions ^^^^^^^^^^^^^^^^^^^^^^ .. doxygengroup:: nomp_other_utils :project: libnomp - :content-only: + :members: diff --git a/docs/user-api.rst b/docs/user-api.rst index 93d30a83..4f183865 100644 --- a/docs/user-api.rst +++ b/docs/user-api.rst @@ -8,21 +8,15 @@ User API Data Types ^^^^^^^^^^ - -Below is a list of data types that are used in the user API. - .. doxygengroup:: nomp_user_types :project: libnomp - :content-only: Functions ^^^^^^^^^ .. doxygengroup:: nomp_user_api :project: libnomp - :content-only: Error Codes ^^^^^^^^^^^ .. doxygengroup:: nomp_error_codes :project: libnomp - :content-only: diff --git a/include/nomp-impl.h b/include/nomp-impl.h index f5245efe..6d210967 100644 --- a/include/nomp-impl.h +++ b/include/nomp-impl.h @@ -16,7 +16,7 @@ /** * @defgroup nomp_internal_types Internal types * - * @brief Internal types used in libnomp. + * @brief Internal types (structures and enums) used by libnomp. */ /** diff --git a/include/nomp.h b/include/nomp.h index 598a49fa..12cb1a17 100644 --- a/include/nomp.h +++ b/include/nomp.h @@ -9,7 +9,8 @@ extern "C" { /** * @defgroup nomp_user_types User types - * @brief Data types used in libnomp user API. + * + * @brief Below is a list of data types that are used in the user API. */ /**