From b1a3d896ab9f34afa970f8f0a990dc178fb70ff9 Mon Sep 17 00:00:00 2001 From: "Samuel K. Gutierrez" Date: Tue, 9 Jul 2024 16:03:49 -0600 Subject: [PATCH] Checkpoint threading work. * Introduce qv_thread_scope_get(). * Bring back partial test-threads test. Signed-off-by: Samuel K. Gutierrez --- include/quo-vadis-thread.h | 6 + src/quo-vadis-thread.cc | 16 +++ src/qvi-group-thread.cc | 11 +- src/qvi-group-thread.h | 14 +- src/qvi-thread.cc | 254 ++++++++++++---------------------- src/qvi-thread.h | 25 +--- tests/CMakeLists.txt | 46 +++---- tests/qvi-test-common.h | 4 + tests/test-threads.c | 274 +++---------------------------------- 9 files changed, 165 insertions(+), 485 deletions(-) diff --git a/include/quo-vadis-thread.h b/include/quo-vadis-thread.h index fc396660..d985af15 100644 --- a/include/quo-vadis-thread.h +++ b/include/quo-vadis-thread.h @@ -47,6 +47,12 @@ qv_pthread_create( qv_scope_t *scope ); +int +qv_thread_scope_get( + qv_scope_intrinsic_t iscope, + qv_scope_t **scope +); + int qv_thread_scope_split_at( qv_scope_t *scope, diff --git a/src/quo-vadis-thread.cc b/src/quo-vadis-thread.cc index c35f092b..c8c5c1ad 100644 --- a/src/quo-vadis-thread.cc +++ b/src/quo-vadis-thread.cc @@ -18,6 +18,7 @@ */ #include "qvi-common.h" // IWYU pragma: keep +#include "qvi-group-thread.h" #include "quo-vadis-thread.h" #include "qvi-scope.h" #include "qvi-utils.h" @@ -25,6 +26,21 @@ #include #endif +int +qv_thread_scope_get( + qv_scope_intrinsic_t iscope, + qv_scope_t **scope +) { + // Create the base process group. + qvi_group_thread_s *zgroup = nullptr; + const int rc = qvi_new(&zgroup); + if (rc != QV_SUCCESS) { + *scope = nullptr; + return rc; + } + return qvi_scope_get(zgroup, iscope, scope); +} + int qv_thread_scope_split( qv_scope_t *scope, diff --git a/src/qvi-group-thread.cc b/src/qvi-group-thread.cc index 05d6d06b..6530173d 100644 --- a/src/qvi-group-thread.cc +++ b/src/qvi-group-thread.cc @@ -26,9 +26,7 @@ qvi_group_thread_s::make_intrinsic( ) { // NOTE: the provided scope doesn't affect how // we create the thread group, so we ignore it. - return qvi_thread_group_create( - th, &th_group - ); + return qvi_thread_group_create(&th_group); } int @@ -40,9 +38,7 @@ qvi_group_thread_s::self( int rc = qvi_new(&ichild); if (rc != QV_SUCCESS) goto out; // Create a group containing a single thread - rc = qvi_thread_group_create_single( - th, &ichild->th_group - ); + rc = qvi_thread_group_create_single(&ichild->th_group); out: if (rc != QV_SUCCESS) { qvi_delete(&ichild); @@ -62,8 +58,7 @@ qvi_group_thread_s::split( if (rc != QV_SUCCESS) goto out; rc = qvi_thread_group_create_from_split( - th, th_group, color, - key, &ichild->th_group + th_group, color, key, &ichild->th_group ); out: if (rc != QV_SUCCESS) { diff --git a/src/qvi-group-thread.h b/src/qvi-group-thread.h index ebba8435..93f70c21 100644 --- a/src/qvi-group-thread.h +++ b/src/qvi-group-thread.h @@ -25,19 +25,10 @@ #include "qvi-thread.h" struct qvi_group_thread_s : public qvi_group_s { - /** - * Initialized qvi_thread_t instance - * embedded in thread group instances. - */ - qvi_thread_t *th = nullptr; /** Underlying group instance. */ qvi_thread_group_t *th_group = nullptr; /** Constructor. */ - qvi_group_thread_s(void) - { - int rc = qvi_thread_new(&th); - if (rc != QV_SUCCESS) throw qvi_runtime_error(); - } + qvi_group_thread_s(void) = default; /** Destructor. */ virtual ~qvi_group_thread_s(void) { @@ -59,8 +50,7 @@ struct qvi_group_thread_s : public qvi_group_s { virtual int barrier(void) { - // TODO(skg) FIXME - return QV_SUCCESS; + return qvi_thread_group_barrier(th_group); } virtual int diff --git a/src/qvi-thread.cc b/src/qvi-thread.cc index b8cb53c4..c45cc58d 100644 --- a/src/qvi-thread.cc +++ b/src/qvi-thread.cc @@ -18,29 +18,64 @@ */ #include "qvi-thread.h" -#include "qvi-group.h" #include "qvi-bbuff.h" #include "qvi-utils.h" #ifdef OPENMP_FOUND #include #endif -using qvi_thread_group_tab_t = std::unordered_map< - qvi_group_id_t, qvi_thread_group_t ->; +static int +qvi_thread_omp_get_num_threads(void) +{ +#ifdef OPENMP_FOUND + return omp_get_num_threads(); +#else + return 1; +#endif +} + +static int +qvi_thread_omp_get_thread_num(void) +{ +#ifdef OPENMP_FOUND + return omp_get_thread_num(); +#else + return 0; +#endif +} -// We need to have one structure for fields -// shared by all threads included in another -// with fields specific to each thread +/** + * We need to have one structure for fields shared by all threads included in + * another with fields specific to each thread. + */ struct qvi_thread_group_shared_s { /** Atomic reference count used for resource freeing. */ std::atomic in_use{0}; - /** ID used for table lookups. */ - qvi_group_id_t tabid = 0; /** Group size. */ - int size = 0; + int size = 0; /** Barrier object (used in scope). */ pthread_barrier_t barrier; + /** Constructor. */ + qvi_thread_group_shared_s(void) = delete; + /** Constructor. */ + qvi_thread_group_shared_s( + int group_size + ) : in_use(group_size) + , size(group_size) + { + const int rc = pthread_barrier_init(&barrier, NULL, group_size); + if (rc != 0) throw qvi_runtime_error(); + } + + static void + destruct( + qvi_thread_group_shared_s *sgroup + ) { + if (--sgroup->in_use == 0) { + pthread_barrier_destroy(&sgroup->barrier); + delete sgroup; + } + } }; struct qvi_thread_group_s { @@ -48,181 +83,77 @@ struct qvi_thread_group_s { * Shared data between threads in the group: * ALL threads point to the same region. */ - qvi_thread_group_shared_t *sdata = nullptr; + qvi_thread_group_shared_s *sdata = nullptr; /** ID (rank) in group: this ID is unique to each thread. */ int id = 0; -}; - -struct qvi_thread_s { - /** Group table (ID to internal structure mapping) */ - qvi_thread_group_tab_t *group_tab = nullptr; + /** Performs object construction, called by the real constructors. */ + void + construct( + int group_size + ) { + qvi_thread_group_shared_s *isdata = nullptr; + #pragma omp single copyprivate(isdata) + { + const int rc = qvi_new(&isdata, group_size); + if (rc != QV_SUCCESS) throw qvi_runtime_error(); + } + sdata = isdata; + id = qvi_thread_omp_get_thread_num(); + } /** Constructor. */ - qvi_thread_s(void) + qvi_thread_group_s(void) { - // Groups - const int rc = qvi_new(&group_tab); - if (rc != QV_SUCCESS) throw qvi_runtime_error(); + construct(qvi_thread_omp_get_num_threads()); + } + /** Constructor. */ + qvi_thread_group_s( + int group_size + ) { + construct(group_size); } /** Destructor. */ - ~qvi_thread_s(void) + ~qvi_thread_group_s(void) { - qvi_delete(&group_tab); + qvi_thread_group_shared_s::destruct(sdata); } }; -int -qvi_thread_new( - qvi_thread_t **th -) { - return qvi_new(th); -} - -void -qvi_thread_free( - qvi_thread_t **th -) { - qvi_delete(th); -} - -/** - * Copies contents of internal structure from src to dst. - */ -// TODO(skg) Do we need this? -static void -cp_thread_group( - const qvi_thread_group_t *src, - qvi_thread_group_t *dst -) { - memmove(dst, src, sizeof(*src)); -} - -static int -next_group_tab_id( - qvi_thread_t *, - qvi_group_id_t *gid -) { - return qvi_group_t::next_id(gid); -} - int qvi_thread_group_new( - qvi_thread_group_t **thgrp + qvi_thread_group_t **group ) { - qvi_thread_group_t *ithgrp = new qvi_thread_group_t(); - qvi_thread_group_shared_t *sdata = nullptr; - -#pragma omp single copyprivate(sdata) - sdata = new qvi_thread_group_shared_t(); - -#pragma omp single - sdata->in_use = omp_get_num_threads(); - - ithgrp->sdata = sdata; - - *thgrp = ithgrp; - return QV_SUCCESS; + return qvi_new(group); } void qvi_thread_group_free( - qvi_thread_group_t **thgrp + qvi_thread_group_t **group ) { - qvi_thread_group_t *ithgrp = *thgrp; - if (!ithgrp) goto out; - - if (--(ithgrp->sdata->in_use) == 0) { - pthread_barrier_destroy(&(ithgrp->sdata->barrier)); - delete ithgrp->sdata; - } - - delete ithgrp; -out: - *thgrp = nullptr; + qvi_delete(group); } static int qvi_thread_group_create_size( - qvi_thread_t *th, qvi_thread_group_t **group, int size ) { - qvi_thread_group_t *igroup = nullptr; - qvi_group_id_t gtid = 0; - int rc, irc; - - rc = qvi_thread_group_new(&igroup); - if (rc != QV_SUCCESS) { - *group = nullptr; - return rc; - } - -#pragma omp single copyprivate(gtid, rc) - rc = next_group_tab_id(th, >id); - if (rc != QV_SUCCESS) goto out; - -#pragma omp single - { - igroup->sdata->tabid = gtid; - igroup->sdata->size = size; - } -#ifdef OPENMP_FOUND - igroup->id = omp_get_thread_num(); -#else - igroup->id = 0; -#endif - -#pragma omp single copyprivate(irc) - irc = pthread_barrier_init(&(igroup->sdata->barrier),NULL,igroup->sdata->size); - if (irc != 0) { - rc = QV_ERR_INTERNAL; - goto out; - } - - //Insert the whole group structure or just the shared part?? -#pragma omp single - th->group_tab->insert({gtid, *igroup}); - -out: - if (rc != QV_SUCCESS) { - qvi_thread_group_free(&igroup); - } - - *group = igroup; - return QV_SUCCESS; + return qvi_new(group, size); } int qvi_thread_group_create( - qvi_thread_t *th, qvi_thread_group_t **group ) { -#ifdef OPENMP_FOUND - return qvi_thread_group_create_size(th, group, omp_get_num_threads()); -#else - return qvi_thread_group_create_size(th, group, 1); /* Size to fix here */ -#endif + return qvi_thread_group_create_size( + group, qvi_thread_omp_get_num_threads() + ); } int qvi_thread_group_create_single( - qvi_thread_t *th, qvi_thread_group_t **group ) { - return qvi_thread_group_create_size(th, group, 1); -} - -int -qvi_thread_group_lookup_by_id( - qvi_thread_t *th, - qvi_group_id_t id, - qvi_thread_group_t *group -) { - auto got = th->group_tab->find(id); - if (got == th->group_tab->end()) { - return QV_ERR_NOT_FOUND; - } - cp_thread_group(&got->second, group); - return QV_SUCCESS; + return qvi_thread_group_create_size(group, 1); } int @@ -435,7 +366,6 @@ qvi_get_subgroup_info( int qvi_thread_group_create_from_split( - qvi_thread_t *th, const qvi_thread_group_t *parent, int color, int key, @@ -443,6 +373,7 @@ qvi_thread_group_create_from_split( ) #ifndef OPENMP_FOUND { + // TODO(skg) This should return self. *child = nullptr; return QV_SUCCESS; } @@ -454,14 +385,13 @@ qvi_thread_group_create_from_split( int sgrp_rank = -1; /* subgroup rank */ int num_sgrp = -1; /* number of subgroups */ qvi_thread_group_t *new_group = nullptr; - qvi_group_id_t gtid; /* this used to internally allocate things */ /* in a copyprivate fashion */ //qvi_thread_group_t **new_group_ptr_array = nullptr; //qvi_thread_group_t *tmp_group = nullptr; - qvi_thread_group_shared_t **sdata_ptr_array = nullptr; - qvi_thread_group_shared_t *tmp_sdata = nullptr; + qvi_thread_group_shared_s **sdata_ptr_array = nullptr; + qvi_thread_group_shared_s *tmp_sdata = nullptr; omp_lock_t *lock_ptr = nullptr; // use pthread_mutex instead ??*/ if (!parent) { @@ -493,11 +423,11 @@ qvi_thread_group_create_from_split( /* sdata pointer allocation */ #pragma omp single copyprivate(sdata_ptr_array) - sdata_ptr_array = new qvi_thread_group_shared_t *[num_sgrp](); + sdata_ptr_array = new qvi_thread_group_shared_s *[num_sgrp](); for(int i = 0 ; i < num_sgrp ; i++) { #pragma omp single copyprivate(tmp_sdata) - tmp_sdata = new qvi_thread_group_shared_t(); + //tmp_sdata = new qvi_thread_group_shared_s(); /* Since it's shared, only the root(s) need(s) to set this */ if ((newid == 0) && (i == sgrp_rank)) { sdata_ptr_array[i] = tmp_sdata; @@ -512,15 +442,8 @@ qvi_thread_group_create_from_split( /* Only the root(s) need(s) to initialize this */ if (newid == 0) { - omp_set_lock(lock_ptr); - rc = next_group_tab_id(th, >id); - omp_unset_lock(lock_ptr); - - sdata_ptr_array[sgrp_rank]->tabid = gtid; - sdata_ptr_array[sgrp_rank]->size = sgrp_size; - sdata_ptr_array[sgrp_rank]->in_use = sgrp_size; - + //sdata_ptr_array[sgrp_rank]->in_use = sgrp_size; pthread_barrier_init(&(sdata_ptr_array[sgrp_rank]->barrier),NULL,sgrp_size); } #pragma omp barrier @@ -528,13 +451,6 @@ qvi_thread_group_create_from_split( new_group->sdata = sdata_ptr_array[sgrp_rank]; new_group->id = newid; - /* Only the root(s) need(s) to insert groups */ - if (newid == 0) { - omp_set_lock(lock_ptr); - th->group_tab->insert({gtid, *new_group}); - omp_unset_lock(lock_ptr); - } - *child = new_group; #pragma omp barrier // to prevent the quickest thread to remove data before all others have used it #pragma omp single diff --git a/src/qvi-thread.h b/src/qvi-thread.h index 9ac2f913..bc6d8c18 100644 --- a/src/qvi-thread.h +++ b/src/qvi-thread.h @@ -19,16 +19,9 @@ #include "qvi-common.h" // Forward declarations. - -struct qvi_thread_group_shared_s; -typedef struct qvi_thread_group_shared_s qvi_thread_group_shared_t; - struct qvi_thread_group_s; typedef struct qvi_thread_group_s qvi_thread_group_t; -struct qvi_thread_s; -typedef struct qvi_thread_s qvi_thread_t; - /** * Mapping policies types. */ @@ -57,16 +50,6 @@ typedef struct qv_layout_s { } qv_layout_t; */ -int -qvi_thread_new( - qvi_thread_t **th -); - -void -qvi_thread_free( - qvi_thread_t **th -); - int qvi_thread_group_size( const qvi_thread_group_t *group @@ -82,6 +65,11 @@ qvi_thread_group_free( qvi_thread_group_t **group ); +int +qvi_thread_group_barrier( + qvi_thread_group_t *group +); + int qvi_thread_group_id( const qvi_thread_group_t *group @@ -89,19 +77,16 @@ qvi_thread_group_id( int qvi_thread_group_create( - qvi_thread_t *proc, qvi_thread_group_t **group ); int qvi_thread_group_create_single( - qvi_thread_t *proc, qvi_thread_group_t **group ); int qvi_thread_group_create_from_split( - qvi_thread_t *th, const qvi_thread_group_t *parent, int color, int key, diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 20f71fae..a1d0909b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -46,16 +46,16 @@ set_tests_properties( ################################################################################ ################################################################################ if (OPENMP_FOUND) - # add_executable( - # test-threads - # test-threads.c - # ) - # - # target_link_libraries( - # test-threads - # quo-vadis - # OpenMP::OpenMP_C - # ) + add_executable( + test-threads + test-threads.c + ) + + target_link_libraries( + test-threads + quo-vadis + OpenMP::OpenMP_C + ) add_executable( test-openmp @@ -67,20 +67,20 @@ if (OPENMP_FOUND) OpenMP::OpenMP_C ) - # set_target_properties( - # test-threads - # test-openmp - # PROPERTIES LINKER_LANGUAGE C - # ) + set_target_properties( + test-threads + test-openmp + PROPERTIES LINKER_LANGUAGE C + ) - # add_test( - # NAME - # threads - # COMMAND - # bash -c "export QV_PORT=\"55999\" && \ - # ( ${CMAKE_SOURCE_DIR}/tests/exec-timeout.sh ../src/quo-vadisd 5 & ) && \ - # ${CMAKE_CURRENT_BINARY_DIR}/test-threads" - # ) + add_test( + NAME + threads + COMMAND + bash -c "export QV_PORT=\"55999\" && \ + ( ${CMAKE_SOURCE_DIR}/tests/exec-timeout.sh ../src/quo-vadisd 5 & ) && \ + ${CMAKE_CURRENT_BINARY_DIR}/test-threads" + ) # Set threads test properties. # TODO(skg) ASAN detects a leak sometimes, so remove from core for now. diff --git a/tests/qvi-test-common.h b/tests/qvi-test-common.h index d4eacfe1..8ea82da1 100644 --- a/tests/qvi-test-common.h +++ b/tests/qvi-test-common.h @@ -18,6 +18,10 @@ #include "quo-vadis.h" +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + #include #include #include diff --git a/tests/test-threads.c b/tests/test-threads.c index 7f05fedd..322e9c21 100644 --- a/tests/test-threads.c +++ b/tests/test-threads.c @@ -1,276 +1,44 @@ /* -*- Mode: C; c-basic-offset:4; indent-tabs-mode:nil -*- */ -/* - * Copyright (c) 2020-2023 Triad National Security, LLC - * All rights reserved. - * - * Copyright (c) 2020 Lawrence Livermore National Security, LLC - * All rights reserved. - * - * Copyright (c) 2022 Inria. - * All rights reserved. - * - * Copyright (c) 2022 Bordeaux INP. - * All rights reserved. - * - * This file is part of the quo-vadis project. See the LICENSE file at the - * top-level directory of this distribution. - */ /** * @file test-threads.c */ -#include "quo-vadis-thread.h" -#include "qvi-macros.h" #include "qvi-test-common.h" - -#include -#include -#include -#include -#include - -#ifdef _OPENMP +#include "quo-vadis-thread.h" #include -#endif - -static void -scope_report( - qv_context_t *ctx, - int pid, - qv_scope_t *scope, - const char *scope_name -) { - char const *ers = NULL; - - int taskid; - int rc = qv_scope_taskid(ctx, scope, &taskid); - if (rc != QV_SUCCESS) { - ers = "qv_scope_taskid() failed"; - qvi_test_panic("%s (rc=%s)", ers, qv_strerr(rc)); - } - - int ntasks; - rc = qv_scope_ntasks(ctx, scope, &ntasks); - if (rc != QV_SUCCESS) { - ers = "qv_scope_ntasks() failed"; - qvi_test_panic("%s (rc=%s)", ers, qv_strerr(rc)); - } - printf("[%d] %s taskid is %d\n", pid, scope_name, taskid); - printf("[%d] %s ntasks is %d\n", pid, scope_name, ntasks); - - rc = qv_scope_barrier(ctx, scope); - if (rc != QV_SUCCESS) { - ers = "qv_scope_barrier() failed"; - qvi_test_panic("%s (rc=%s)", ers, qv_strerr(rc)); - } -} - -static void -change_bind( - qv_context_t *ctx, - int pid, - qv_scope_t *scope -) { - char const *ers = NULL; - - if (getenv("HWLOC_XMLFILE")) { - if (pid == 0) { - printf("*** Using synthetic topology. " - "Skipping change_bind tests. ***\n"); - } - return; - } +int +main(void) +{ + char *ers = NULL; + int rc = QV_SUCCESS; - int rc = qv_bind_push(ctx, scope); - if (rc != QV_SUCCESS) { - ers = "qv_bind_push() failed"; - qvi_test_panic("%s (rc=%s)", ers, qv_strerr(rc)); - } +#pragma omp parallel +#pragma omp single + printf("# Starting OpenMP Test (nthreads=%d)\n", omp_get_num_threads()); - char *bind1s; - rc = qv_bind_string(ctx, QV_BIND_STRING_AS_LIST, &bind1s); - if (rc != QV_SUCCESS) { - ers = "qv_bind_string() failed"; - qvi_test_panic("%s (rc=%s)", ers, qv_strerr(rc)); - } - printf("[%d] New cpubind is %s\n", pid,bind1s); - free(bind1s); - - rc = qv_bind_pop(ctx); +#pragma omp parallel private(ers, rc) +{ + qv_scope_t *base_scope = NULL; + rc = qv_thread_scope_get( + QV_SCOPE_PROCESS, + &base_scope + ); if (rc != QV_SUCCESS) { - ers = "qv_bind_pop() failed"; + ers = "qv_thread_scope_get() failed"; qvi_test_panic("%s (rc=%s)", ers, qv_strerr(rc)); } - char *bind2s; - rc = qv_bind_string(ctx, QV_BIND_STRING_AS_LIST, &bind2s); - if (rc != QV_SUCCESS) { - ers = "qv_bind_string() failed"; - qvi_test_panic("%s (rc=%s)", ers, qv_strerr(rc)); - } - printf("[%d] Popped cpubind is %s\n", pid, bind2s); - free(bind2s); + qvi_test_scope_report(base_scope, "base_scope"); - // TODO(skg) Add test to make popped is same as original. - rc = qv_scope_barrier(ctx, scope); + rc = qv_scope_free(base_scope); if (rc != QV_SUCCESS) { - ers = "qv_scope_barrier() failed"; + ers = "qv_scope_free() failed"; qvi_test_panic("%s (rc=%s)", ers, qv_strerr(rc)); } } - -int -main(void) -{ - char const *ers = NULL; - int rc = QV_SUCCESS; - - fprintf(stdout,"# Starting test\n"); - -#pragma omp parallel private(ers, rc) //num_threads(4) - { - int pid = syscall(SYS_gettid); - int n_cores; - int n_pus; - - qv_context_t *ctx; - rc = qv_thread_context_create(&ctx); - if (rc != QV_SUCCESS) { - ers = "qv_process_context_create() failed"; - qvi_test_panic("%s (rc=%s)", ers, qv_strerr(rc)); - } - - qv_scope_t *base_scope; - rc = qv_scope_get( - ctx, - QV_SCOPE_PROCESS, - &base_scope - ); - if (rc != QV_SUCCESS) { - ers = "qv_scope_get() failed"; - qvi_test_panic("%s (rc=%s)", ers, qv_strerr(rc)); - } - scope_report(ctx, pid, base_scope, "base_scope"); - - rc = qv_scope_nobjs( - ctx, - base_scope, - QV_HW_OBJ_CORE, - &n_cores - ); - if (rc != QV_SUCCESS) { - ers = "qv_scope_nobjs() failed"; - qvi_test_panic("%s (rc=%s)", ers, qv_strerr(rc)); - } - printf("[%d] Number of CORES in base_scope is %d\n", pid, n_cores); - - rc = qv_scope_nobjs( - ctx, - base_scope, - QV_HW_OBJ_PU, - &n_pus - ); - if (rc != QV_SUCCESS) { - ers = "qv_scope_nobjs() failed"; - qvi_test_panic("%s (rc=%s)", ers, qv_strerr(rc)); - } - printf("[%d] Number of PUS in base_scope is %d\n", pid, n_pus); - - rc = qv_scope_free(ctx, base_scope); - if (rc != QV_SUCCESS) { - ers = "qv_scope_free() failed"; - qvi_test_panic("%s (rc=%s)", ers, qv_strerr(rc)); - } - - qv_scope_t *self_scope; - rc = qv_scope_get( - ctx, - QV_SCOPE_PROCESS, - &self_scope - ); - if (rc != QV_SUCCESS) { - ers = "qv_scope_get(QV_SCOPE_PROCESS) failed"; - qvi_test_panic("%s (rc=%s)", ers, qv_strerr(rc)); - } - scope_report(ctx, pid, self_scope, "self_scope"); - - rc = qv_scope_nobjs( - ctx, - self_scope, - QV_HW_OBJ_CORE, - &n_cores - ); - if (rc != QV_SUCCESS) { - ers = "qv_scope_nobjs() failed"; - qvi_test_panic("%s (rc=%s)", ers, qv_strerr(rc)); - } - printf("[%d] Number of CORES in self_scope is %d\n", pid, n_cores); - - rc = qv_scope_nobjs( - ctx, - self_scope, - QV_HW_OBJ_PU, - &n_pus - ); - if (rc != QV_SUCCESS) { - ers = "qv_scope_nobjs() failed"; - qvi_test_panic("%s (rc=%s)", ers, qv_strerr(rc)); - } - printf("[%d] Number of PUS in self_scope is %d\n", pid, n_pus); - - char *binds; - rc = qv_bind_string(ctx, 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)); - } - printf("[%d] Current cpubind is %s\n", pid, binds); - free(binds); - - qv_scope_t *sub_scope; - rc = qv_scope_split( - ctx, - self_scope, - 2, // npieces - omp_get_thread_num() %2, // group id - &sub_scope - ); - if (rc != QV_SUCCESS) { - ers = "qv_scope_split() failed"; - qvi_test_panic("%s (rc=%s)", ers, qv_strerr(rc)); - } - scope_report(ctx, pid, sub_scope, "sub_scope"); - - change_bind(ctx, pid, sub_scope); - - rc = qv_scope_free(ctx, sub_scope); - if (rc != QV_SUCCESS) { - ers = "qv_scope_free() failed"; - qvi_test_panic("%s (rc=%s)", ers, qv_strerr(rc)); - } - - rc = qv_scope_free(ctx, self_scope); - if (rc != QV_SUCCESS) { - ers = "qv_scope_free() failed"; - qvi_test_panic("%s (rc=%s)", ers, qv_strerr(rc)); - } - - rc = qv_context_barrier(ctx); - if (rc != QV_SUCCESS) { - ers = "qv_context_barrier() failed"; - qvi_test_panic("%s (rc=%s)", ers, qv_strerr(rc)); - } - - rc = qv_thread_context_free(ctx); - if (rc != QV_SUCCESS) { - ers = "qv_thread_context_free failed"; - qvi_test_panic("%s (rc=%s)", ers, qv_strerr(rc)); - } - - } - return EXIT_SUCCESS; + return EXIT_SUCCESS; } /*