Skip to content

Commit 061261c

Browse files
committed
update OpenMP linking and test environment setup
1 parent c83f0ef commit 061261c

File tree

5 files changed

+110
-11
lines changed

5 files changed

+110
-11
lines changed

cmake/openmp.cmake

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,22 @@ endfunction()
2020

2121
function(ppc_link_openmp exec_func_lib)
2222
find_package(OpenMP REQUIRED)
23-
target_link_libraries(${exec_func_lib} PUBLIC ${OpenMP_libomp_LIBRARY}
24-
OpenMP::OpenMP_CXX)
23+
# Link the canonical imported target if available
24+
if (TARGET OpenMP::OpenMP_CXX)
25+
target_link_libraries(${exec_func_lib} PUBLIC OpenMP::OpenMP_CXX)
26+
endif()
27+
28+
if (APPLE)
29+
# Homebrew libomp common paths
30+
find_path(LIBOMP_INCLUDE_DIR omp.h HINTS /opt/homebrew/opt/libomp/include /usr/local/opt/libomp/include)
31+
find_library(LIBOMP_LIBRARY omp HINTS /opt/homebrew/opt/libomp/lib /usr/local/opt/libomp/lib)
32+
if (LIBOMP_INCLUDE_DIR)
33+
target_include_directories(${exec_func_lib} PUBLIC ${LIBOMP_INCLUDE_DIR})
34+
endif()
35+
if (LIBOMP_LIBRARY)
36+
target_link_libraries(${exec_func_lib} PUBLIC ${LIBOMP_LIBRARY})
37+
# Ensure Clang generates OpenMP code
38+
target_compile_options(${exec_func_lib} PUBLIC -Xclang -fopenmp)
39+
endif()
40+
endif()
2541
endfunction()

modules/util/include/func_test_util.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ class BaseRunFuncTests : public ::testing::TestWithParam<FuncTestParam<InType, O
6161

6262
ValidateTestName(test_name);
6363

64+
const auto test_env_scope = ppc::util::test::MakePerTestEnvForCurrentGTest(test_name);
65+
6466
if (IsTestDisabled(test_name)) {
6567
GTEST_SKIP();
6668
}

modules/util/include/perf_test_util.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ class BaseRunPerfTests : public ::testing::TestWithParam<PerfTestParam<InType, O
7777
GTEST_SKIP();
7878
}
7979

80+
const auto test_env_scope = ppc::util::test::MakePerTestEnvForCurrentGTest(test_name);
81+
8082
task_ = task_getter(GetTestInputData());
8183
ppc::performance::Perf perf(task_);
8284
ppc::performance::PerfAttr perf_attr;

modules/util/include/util.hpp

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
#pragma once
22

3+
#include <algorithm>
34
#include <atomic>
5+
#include <cctype>
46
#include <cstdint>
57
#include <cstdlib>
8+
#include <filesystem>
69
#include <memory>
10+
#include <sstream>
711
#include <string>
12+
#include <string_view>
13+
#include <system_error>
814
#include <typeinfo>
915
#ifdef __GNUG__
1016
# include <cxxabi.h>
@@ -17,6 +23,9 @@
1723
# pragma warning(disable : 4459)
1824
#endif
1925

26+
#include <gtest/gtest.h>
27+
28+
#include <libenvpp/detail/environment.hpp>
2029
#include <nlohmann/json.hpp>
2130

2231
/// @brief JSON namespace used for settings and config parsing.
@@ -55,7 +64,7 @@ class DestructorFailureFlag {
5564

5665
enum class GTestParamIndex : uint8_t { kTaskGetter, kNameTest, kTestParams };
5766

58-
std::string GetAbsoluteTaskPath(const std::string &id_path, const std::string &relative_path);
67+
std::string GetAbsoluteTaskPath(const std::string& id_path, const std::string& relative_path);
5968
int GetNumThreads();
6069
int GetNumProc();
6170
double GetTaskMaxTime();
@@ -66,13 +75,13 @@ std::string GetNamespace() {
6675
std::string name = typeid(T).name();
6776
#ifdef __GNUC__
6877
int status = 0;
69-
std::unique_ptr<char, void (*)(void *)> demangled{abi::__cxa_demangle(name.c_str(), nullptr, nullptr, &status),
70-
std::free};
78+
std::unique_ptr<char, void (*)(void*)> demangled{abi::__cxa_demangle(name.c_str(), nullptr, nullptr, &status),
79+
std::free};
7180
name = (status == 0) ? demangled.get() : name;
7281
#endif
7382
#ifdef _MSC_VER
7483
const std::string prefixes[] = {"class ", "struct ", "enum ", "union "};
75-
for (const auto &prefix : prefixes) {
84+
for (const auto& prefix : prefixes) {
7685
if (name.starts_with(prefix)) {
7786
name = name.substr(prefix.size());
7887
break;
@@ -90,4 +99,57 @@ inline std::shared_ptr<nlohmann::json> InitJSONPtr() {
9099

91100
bool IsUnderMpirun();
92101

102+
namespace test {
103+
104+
[[nodiscard]] inline std::string SanitizeToken(std::string_view token_sv) {
105+
std::string token{token_sv};
106+
auto is_allowed = [](char c) {
107+
return std::isalnum(static_cast<unsigned char>(c)) || c == '_' || c == '-' || c == '.';
108+
};
109+
std::ranges::replace(token, ' ', '_');
110+
for (char& ch : token) {
111+
if (!is_allowed(ch)) {
112+
ch = '_';
113+
}
114+
}
115+
return token;
116+
}
117+
118+
class ScopedPerTestEnv {
119+
public:
120+
explicit ScopedPerTestEnv(const std::string& token)
121+
: set_uid_("PPC_TEST_UID", token), set_tmp_("PPC_TEST_TMPDIR", CreateTmpDir(token)) {}
122+
123+
private:
124+
static std::string CreateTmpDir(const std::string& token) {
125+
namespace fs = std::filesystem;
126+
const fs::path tmp = fs::temp_directory_path() / (std::string("ppc_test_") + token);
127+
std::error_code ec;
128+
fs::create_directories(tmp, ec);
129+
(void)ec;
130+
return tmp.string();
131+
}
132+
133+
env::detail::set_scoped_environment_variable set_uid_;
134+
env::detail::set_scoped_environment_variable set_tmp_;
135+
};
136+
137+
[[nodiscard]] inline std::string MakeCurrentGTestToken(std::string_view fallback_name) {
138+
const auto* unit = ::testing::UnitTest::GetInstance();
139+
const auto* info = (unit != nullptr) ? unit->current_test_info() : nullptr;
140+
std::ostringstream os;
141+
if (info != nullptr) {
142+
os << info->test_suite_name() << "." << info->name();
143+
} else {
144+
os << fallback_name;
145+
}
146+
return SanitizeToken(os.str());
147+
}
148+
149+
inline ScopedPerTestEnv MakePerTestEnvForCurrentGTest(std::string_view fallback_name) {
150+
return ScopedPerTestEnv(MakeCurrentGTestToken(fallback_name));
151+
}
152+
153+
} // namespace test
154+
93155
} // namespace ppc::util

scripts/run_tests.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -135,30 +135,47 @@ def run_processes(self, additional_mpi_args):
135135
)
136136

137137
mpi_running = (
138-
[self.mpi_exec] + shlex.split(additional_mpi_args) + ["-np", ppc_num_proc]
138+
[self.mpi_exec]
139+
+ shlex.split(additional_mpi_args)
140+
+ [
141+
"-x",
142+
"PPC_NUM_THREADS",
143+
"-x",
144+
"OMP_NUM_THREADS",
145+
"-np",
146+
ppc_num_proc,
147+
]
139148
)
140149
if not self.__ppc_env.get("PPC_ASAN_RUN"):
141150
for task_type in ["all", "mpi"]:
142151
self.__run_exec(
143152
mpi_running
144153
+ [str(self.work_dir / "ppc_func_tests")]
145-
+ self.__get_gtest_settings(1, "_" + task_type)
154+
+ self.__get_gtest_settings(1, "_" + task_type + "_")
146155
)
147156

148157
def run_performance(self):
149158
if not self.__ppc_env.get("PPC_ASAN_RUN"):
150-
mpi_running = [self.mpi_exec, "-np", self.__ppc_num_proc]
159+
mpi_running = [
160+
self.mpi_exec,
161+
"-x",
162+
"PPC_NUM_THREADS",
163+
"-x",
164+
"OMP_NUM_THREADS",
165+
"-np",
166+
self.__ppc_num_proc,
167+
]
151168
for task_type in ["all", "mpi"]:
152169
self.__run_exec(
153170
mpi_running
154171
+ [str(self.work_dir / "ppc_perf_tests")]
155-
+ self.__get_gtest_settings(1, "_" + task_type)
172+
+ self.__get_gtest_settings(1, "_" + task_type + "_")
156173
)
157174

158175
for task_type in ["omp", "seq", "stl", "tbb"]:
159176
self.__run_exec(
160177
[str(self.work_dir / "ppc_perf_tests")]
161-
+ self.__get_gtest_settings(1, "_" + task_type)
178+
+ self.__get_gtest_settings(1, "_" + task_type + "_")
162179
)
163180

164181

0 commit comments

Comments
 (0)