Skip to content

Commit

Permalink
Update thread example. (#209)
Browse files Browse the repository at this point in the history
Experiment with how straightforward this interface can become. Also
provides an example on how one might structure this in their OpenMP
code.

Signed-off-by: Samuel K. Gutierrez <[email protected]>
  • Loading branch information
samuelkgutierrez authored Jul 11, 2024
1 parent f400261 commit 244c3ae
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 49 deletions.
1 change: 0 additions & 1 deletion src/qvi-group-thread.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ int
qvi_group_thread_s::self(
qvi_group_t **child
) {
qvi_log_debug("=======================SELF");
qvi_group_thread_t *ichild = nullptr;
int rc = qvi_new(&ichild);
if (rc != QV_SUCCESS) goto out;
Expand Down
149 changes: 101 additions & 48 deletions tests/test-threads.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,22 @@
#include "quo-vadis-thread.h"
#include <omp.h>

typedef struct {
qv_scope_t *scope;
int size;
int id;
} scopei;

static void
emit_iter_info(
qv_scope_t *scope,
scopei *sinfo,
int i
) {
char const *ers = NULL;
char *binds;
const int rc = qv_scope_bind_string(scope, QV_BIND_STRING_AS_LIST, &binds);
const int rc = qv_scope_bind_string(
sinfo->scope, QV_BIND_STRING_AS_LIST, &binds
);
if (rc != QV_SUCCESS) {
ers = "qv_bind_string() failed";
qvi_test_panic("%s (rc=%s)", ers, qv_strerr(rc));
Expand All @@ -28,81 +36,126 @@ emit_iter_info(
free(binds);
}

int
main(void)
{
// Make sure nested parallism is on.
omp_set_nested(1);
#pragma omp parallel
#pragma omp master
printf("# Starting OpenMP Test (nthreads=%d)\n", omp_get_num_threads());

#pragma omp parallel
{
static void
scopei_fill(
scopei *sinfo
) {
char *ers = NULL;
int rc = QV_SUCCESS;
qv_scope_t *base_scope = NULL;
rc = qv_thread_scope_get(
QV_SCOPE_PROCESS,
&base_scope
);

int rc = qv_scope_ntasks(sinfo->scope, &sinfo->size);
if (rc != QV_SUCCESS) {
ers = "qv_thread_scope_get() failed";
ers = "qv_scope_ntasks() failed";
qvi_test_panic("%s (rc=%s)", ers, qv_strerr(rc));
}

int taskid = 0;
rc = qv_scope_taskid(base_scope, &taskid);
rc = qv_scope_taskid(sinfo->scope, &sinfo->id);
if (rc != QV_SUCCESS) {
ers = "qv_scope_taskid() failed";
qvi_test_panic("%s (rc=%s)", ers, qv_strerr(rc));
}
}

qv_scope_t *sub_scope;
rc = qv_scope_split(
base_scope, 2, taskid, &sub_scope
);
static void
scopei_free(
scopei *sinfo
) {
char *ers = NULL;
const int rc = qv_scope_free(sinfo->scope);
if (rc != QV_SUCCESS) {
ers = "qv_scope_split_at() failed";
ers = "qv_scope_free() failed";
qvi_test_panic("%s (rc=%s)", ers, qv_strerr(rc));
}
}

int nsubtasks = 0;
rc = qv_scope_ntasks(base_scope, &nsubtasks);
static void
scopei_base(
scopei *sinfo
) {
char *ers = NULL;
const int rc = qv_thread_scope_get(
QV_SCOPE_PROCESS, &sinfo->scope
);
if (rc != QV_SUCCESS) {
ers = "qv_scope_ntasks() failed";
ers = "qv_thread_scope_get() failed";
qvi_test_panic("%s (rc=%s)", ers, qv_strerr(rc));
}
scopei_fill(sinfo);
}

qv_scope_bind_push(sub_scope);
#pragma omp task
#pragma omp parallel for num_threads(nsubtasks)
for (int i = 0; i < 8; ++i) {
emit_iter_info(sub_scope, i);
}
qv_scope_bind_pop(sub_scope);
/**
* Creates the execution policy scope.
*/
static void
scopei_ep(
scopei *sinfo
) {
// Get the base (parent) scope.
scopei pinfo;
scopei_base(&pinfo);

qv_scope_bind_push(sub_scope);
#pragma omp task
#pragma omp parallel num_threads(1)
{
//qvi_test_emit_task_bind(sub_scope);
char *ers = NULL;
int rc = qv_scope_split(
pinfo.scope, 2, pinfo.id, &sinfo->scope
);
if (rc != QV_SUCCESS) {
ers = "qv_scope_split_at() failed";
qvi_test_panic("%s (rc=%s)", ers, qv_strerr(rc));
}
#pragma omp barrier
qv_scope_bind_pop(sub_scope);
scopei_fill(sinfo);
// We don't need this anymore.
scopei_free(&pinfo);
}

rc = qv_scope_free(sub_scope);
static void
scopei_ep_push(
scopei *sinfo
) {
char *ers = NULL;
const int rc = qv_scope_bind_push(sinfo->scope);
if (rc != QV_SUCCESS) {
ers = "qv_scope_free() failed";
ers = "qv_scope_bind_push() failed";
qvi_test_panic("%s (rc=%s)", ers, qv_strerr(rc));
}
}

rc = qv_scope_free(base_scope);
static void
scopei_ep_pop(
scopei *sinfo
) {
// Make sure everyone is done with the execution policy before we pop.
#pragma omp barrier
char *ers = NULL;
const int rc = qv_scope_bind_pop(sinfo->scope);
if (rc != QV_SUCCESS) {
ers = "qv_scope_free() failed";
ers = "qv_scope_bind_pop() failed";
qvi_test_panic("%s (rc=%s)", ers, qv_strerr(rc));
}
}

int
main(void)
{
// Make sure nested parallism is on.
omp_set_nested(1);
#pragma omp parallel
#pragma omp master
printf("# Starting OpenMP Test (nthreads=%d)\n", omp_get_num_threads());

#pragma omp parallel
{
scopei ep_sinfo;
scopei_ep(&ep_sinfo);

scopei_ep_push(&ep_sinfo);
#pragma omp task
#pragma omp parallel for num_threads(ep_sinfo.size)
for (int i = 0; i < 8; ++i) {
emit_iter_info(&ep_sinfo, i);
}
scopei_ep_pop(&ep_sinfo);

scopei_free(&ep_sinfo);
}
return EXIT_SUCCESS;
}

Expand Down

0 comments on commit 244c3ae

Please sign in to comment.