-
Notifications
You must be signed in to change notification settings - Fork 99
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Perf Tests: adding utilities and instantiation wrapper
The goal of this work is to create a common core infrastructure for the performance test in order to simplify maintenance. Here two ideas are introduced: 1. the instantiation wrapper 2. the common input parser both are trying to capture some of the implementation of our performance test in generic functions that can be called instead of duplicating logic around instantiation and command line input parsing. The new parsing routine checks the parameter name and that the associated value can be casted properly. It also add some logic to remove the arguments from argv and argc once they are parsed properly.
- Loading branch information
Showing
3 changed files
with
364 additions
and
183 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
//@HEADER | ||
// ************************************************************************ | ||
// | ||
// Kokkos v. 4.0 | ||
// Copyright (2022) National Technology & Engineering | ||
// Solutions of Sandia, LLC (NTESS). | ||
// | ||
// Under the terms of Contract DE-NA0003525 with NTESS, | ||
// the U.S. Government retains certain rights in this software. | ||
// | ||
// Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://kokkos.org/LICENSE for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//@HEADER | ||
// | ||
// Created by Berger-Vergiat, Luc on 2/6/23. | ||
// | ||
|
||
#ifndef KOKKOSKERNELS_PERF_TEST_INSTANTIATION_HPP | ||
#define KOKKOSKERNELS_PERF_TEST_INSTANTIATION_HPP | ||
|
||
#include "KokkosKernels_perf_test_utilities.hpp" | ||
|
||
#ifndef KOKKOSKERNELS_PERF_TEST_NAME | ||
#error "The macro KOKKOSKERNELS_PERF_TEST_NAME was not defined" | ||
#endif | ||
|
||
int main_instantiation(int argc, char** argv) { | ||
perf_test::CommonInputParams params; | ||
perf_test::parse_common_options(argc, argv, params); | ||
|
||
/* Assumption is that use_openmp/use_threads variables are */ | ||
/* provided as numbers of threads */ | ||
int num_threads = 1; | ||
if (params.use_openmp) { | ||
num_threads = params.use_openmp; | ||
} else if (params.use_threads) { | ||
num_threads = params.use_threads; | ||
} | ||
|
||
int device_id = 0; | ||
if (params.use_cuda) | ||
device_id = params.use_cuda - 1; | ||
else if (params.use_hip) | ||
device_id = params.use_hip - 1; | ||
else if (params.use_sycl) | ||
device_id = params.use_sycl - 1; | ||
|
||
Kokkos::initialize(Kokkos::InitializationSettings() | ||
.set_num_threads(num_threads) | ||
.set_device_id(device_id)); | ||
Kokkos::print_configuration(std::cout); | ||
std::cout << '\n'; | ||
|
||
bool ran = false; | ||
|
||
if (params.use_openmp) { | ||
#if defined(KOKKOS_ENABLE_OPENMP) | ||
std::cout << "Running on OpenMP backend.\n"; | ||
KOKKOSKERNELS_PERF_TEST_NAME<Kokkos::OpenMP>(argc, argv, params); | ||
ran = true; | ||
#else | ||
std::cout << "ERROR: OpenMP requested, but not available.\n"; | ||
Kokkos::finalize(); | ||
return 1; | ||
#endif | ||
} | ||
if (params.use_threads) { | ||
#if defined(KOKKOS_ENABLE_THREADS) | ||
std::cout << "Running on Threads backend.\n"; | ||
KOKKOSKERNELS_PERF_TEST_NAME<Kokkos::Threads>(argc, argv, params); | ||
ran = true; | ||
#else | ||
std::cout << "ERROR: Threads requested, but not available.\n"; | ||
Kokkos::finalize(); | ||
return 1; | ||
#endif | ||
} | ||
if (params.use_cuda) { | ||
#if defined(KOKKOS_ENABLE_CUDA) | ||
std::cout << "Running on Cuda backend.\n"; | ||
KOKKOSKERNELS_PERF_TEST_NAME<Kokkos::Cuda>(argc, argv, params); | ||
ran = true; | ||
#else | ||
std::cout << "ERROR: CUDA requested, but not available.\n"; | ||
Kokkos::finalize(); | ||
return 1; | ||
#endif | ||
} | ||
if (params.use_hip) { | ||
#if defined(KOKKOS_ENABLE_HIP) | ||
std::cout << "Running on HIP backend.\n"; | ||
KOKKOSKERNELS_PERF_TEST_NAME<Kokkos::HIP>(argc, argv, params); | ||
ran = true; | ||
#else | ||
std::cout << "ERROR: HIP requested, but not available.\n"; | ||
Kokkos::finalize(); | ||
return 1; | ||
#endif | ||
} | ||
if (params.use_sycl) { | ||
#if defined(KOKKOS_ENABLE_SYCL) | ||
std::cout << "Running on SYCL backend.\n"; | ||
KOKKOSKERNELS_PERF_TEST_NAME<Kokkos::Experimental::SYCL>(argc, argv, | ||
params); | ||
ran = true; | ||
#else | ||
std::cout << "ERROR: SYCL requested, but not available.\n"; | ||
Kokkos::finalize(); | ||
return 1; | ||
#endif | ||
} | ||
if (!ran) { | ||
#if defined(KOKKOS_ENABLE_SERIAL) | ||
std::cout << "Running on Serial backend.\n"; | ||
KOKKOSKERNELS_PERF_TEST_NAME<Kokkos::Serial>(argc, argv, params); | ||
#else | ||
std::cout << "ERROR: Tried to run on Serial device (as no parallel" | ||
" backends requested), but Serial is not enabled.\n"; | ||
Kokkos::finalize(); | ||
return 1; | ||
#endif | ||
} | ||
Kokkos::finalize(); | ||
return 0; | ||
} | ||
|
||
// Undefine the macro to avoid potential bad interaction | ||
// with other parts of the code... | ||
#undef KOKKOSKERNELS_PERF_TEST_NAME | ||
|
||
#endif // KOKKOSKERNELS_PERF_TEST_INSTANTIATION_HPP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
//@HEADER | ||
// ************************************************************************ | ||
// | ||
// Kokkos v. 4.0 | ||
// Copyright (2022) National Technology & Engineering | ||
// Solutions of Sandia, LLC (NTESS). | ||
// | ||
// Under the terms of Contract DE-NA0003525 with NTESS, | ||
// the U.S. Government retains certain rights in this software. | ||
// | ||
// Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://kokkos.org/LICENSE for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//@HEADER | ||
// | ||
// Created by Berger-Vergiat, Luc on 2/6/23. | ||
// | ||
|
||
#ifndef KOKKOSKERNELS_PERF_TEST_UTILITIES_HPP | ||
#define KOKKOSKERNELS_PERF_TEST_UTILITIES_HPP | ||
|
||
// Namepsace that defines common utilities | ||
// for performance tests | ||
namespace perf_test { | ||
|
||
struct CommonInputParams { | ||
int use_cuda = 0; | ||
int use_hip = 0; | ||
int use_sycl = 0; | ||
int use_openmp = 0; | ||
int use_threads = 0; | ||
}; | ||
|
||
std::string list_common_options() { | ||
std::ostringstream common_options; | ||
common_options | ||
<< "\t[Required] BACKEND:\n" | ||
<< "\t\t'--threads [numThreads]' |\n" | ||
<< "\t\t'--openmp [numThreads]' |\n" | ||
<< "\t\t'--cuda [deviceIndex]' |\n" | ||
<< "\t\t'--hip [deviceIndex]' |\n" | ||
<< "\t\t'--sycl [deviceIndex]'\n\n" | ||
<< "\tIf no parallel backend is requested, Serial will be used " | ||
"(if enabled)\n\n"; | ||
|
||
return common_options.str(); | ||
} | ||
|
||
void process_arg_int(char const* str_val, int& val) { | ||
errno = 0; | ||
char* ptr_end; | ||
val = std::strtol(str_val, &ptr_end, 10); | ||
|
||
if (str_val == ptr_end) { | ||
std::stringstream ss; | ||
ss << "Error: cannot convert command line argument '" << str_val | ||
<< "' to an integer.\n"; | ||
throw std::invalid_argument(ss.str()); | ||
} | ||
|
||
if (errno == ERANGE) { | ||
std::stringstream ss; | ||
ss << "Error: converted value for command line argument '" << str_val | ||
<< "' falls out of range.\n"; | ||
throw std::invalid_argument(ss.str()); | ||
} | ||
} | ||
|
||
bool check_arg_int(int const i, int const argc, char** argv, char const* name, | ||
int& val) { | ||
if (0 != Test::string_compare_no_case(argv[i], name)) { | ||
return false; | ||
} | ||
|
||
if (i < argc - 1) { | ||
process_arg_int(argv[i + 1], val); | ||
} else { | ||
std::stringstream msg; | ||
msg << name << " input argument needs to be followed by an int"; | ||
throw std::invalid_argument(msg.str()); | ||
} | ||
return true; | ||
} | ||
|
||
bool check_arg_bool(int const i, int const /*argc*/, char** argv, | ||
char const* name, bool& val) { | ||
if (0 != Test::string_compare_no_case(argv[i], name)) { | ||
return false; | ||
} | ||
val = true; | ||
return true; | ||
} | ||
|
||
bool check_arg_str(int const i, int const argc, char** argv, char const* name, | ||
std::string& val) { | ||
if (0 != Test::string_compare_no_case(argv[i], name)) { | ||
return false; | ||
} | ||
|
||
if (i < argc - 1) { | ||
val = std::string(argv[i + 1]); | ||
} else { | ||
std::stringstream msg; | ||
msg << name << " input argument needs to be followed by a string"; | ||
throw std::invalid_argument(msg.str()); | ||
} | ||
return true; | ||
} | ||
|
||
void parse_common_options(int& argc, char** argv, CommonInputParams& params) { | ||
// Skip the program name, start with argIdx=1 | ||
int argIdx = 1; | ||
while (argIdx < argc) { | ||
bool remove_flag = false; | ||
if (check_arg_int(argIdx, argc, argv, "--threads", params.use_threads)) { | ||
remove_flag = true; | ||
} else if (check_arg_int(argIdx, argc, argv, "--openmp", | ||
params.use_openmp)) { | ||
remove_flag = true; | ||
} else if (check_arg_int(argIdx, argc, argv, "--cuda", params.use_cuda)) { | ||
remove_flag = true; | ||
} else if (check_arg_int(argIdx, argc, argv, "--hip", params.use_hip)) { | ||
remove_flag = true; | ||
} else if (check_arg_int(argIdx, argc, argv, "--sycl", params.use_sycl)) { | ||
remove_flag = true; | ||
} | ||
|
||
if (remove_flag) { | ||
// Shift the remainder of the argv list by one. Note that argv has | ||
// (argc + 1) arguments, the last one always being nullptr. The following | ||
// loop moves the trailing nullptr element as well | ||
for (int k = argIdx; k < argc - 1; ++k) { | ||
argv[k] = argv[k + 2]; | ||
argv[k + 1] = argv[k + 3]; | ||
} | ||
argc = argc - 2; | ||
} else { | ||
++argIdx; | ||
} | ||
} | ||
} // parse_common_options() | ||
|
||
} // namespace perf_test | ||
|
||
#endif // KOKKOSKERNELS_PERF_TEST_UTILITIES_HPP |
Oops, something went wrong.