Skip to content

Commit 5cec0a5

Browse files
benchmark/nixlbench: switched to cxxopts
This patch replaces gflags-based parameter parsing with cxxopts-based parsing, and removes the gflags dependency. This change will enable us to support config file-based parameters in upcoming patches. Unfortunately, gflags is not flexible enough for our needs. For example, it does not indicate whether a parameter was explicitly provided by the user or if it is using a default. This functionality is required for correct parameter specification priority: first, a value provided by the user on the command line; then a value from the config file; and finally, the default value. Additionally, gflags does not support dynamically formed arguments, which is needed to handle a list of tasks as discussed. For this use case, the config file would look like: [general] ... num_tasks=2 [task0] local=... remote=... type=write ... [task1] local=... remote=... type=read ... This translates to command line parameters like: --num_tasks=2 --task0.local=... ... --task1.local=... Since gflags is a compile-time mechanism, it cannot support this level of dynamic argument handling. Signed-off-by: Anton Nayshtut <[email protected]>
1 parent c477575 commit 5cec0a5

File tree

6 files changed

+82
-20
lines changed

6 files changed

+82
-20
lines changed

benchmark/nixlbench/meson.build

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,6 @@ if cuda_available
103103
endif
104104
endif
105105

106-
# GFlags
107-
gflags_dep = dependency('gflags', required: true)
108-
109106
# OpenMP
110107
openmp_dep = dependency('openmp', required: true)
111108

@@ -166,7 +163,7 @@ configure_file(
166163
install_dir: get_option('includedir') / 'nixlbench'
167164
)
168165

169-
deps = [gflags_dep, nixl_lib, nixl_build, nixl_serdes, openmp_dep]
166+
deps = [nixl_lib, nixl_build, nixl_serdes, openmp_dep]
170167
args = []
171168
if etcd_available
172169
deps += [etcd_dep]
@@ -208,7 +205,7 @@ if nvshmem_available
208205
nvcc_args += ['-L' + meson.current_build_dir() + '/src/utils']
209206
nvcc_args += ['-L' + meson.current_build_dir() + '/src/runtime']
210207
nvcc_args += ['-L' + meson.current_build_dir() + '/src/worker']
211-
nvcc_args += ['-lnixl', '-lnixl_build', '-lserdes', '-lgflags', '-lcuda', '-lcudart', '-lnvshmem']
208+
nvcc_args += ['-lnixl', '-lnixl_build', '-lserdes', '-lcuda', '-lcudart', '-lnvshmem']
212209
nvcc_args += args
213210
nvcc_cmd_files = [
214211
meson.current_build_dir() + '/src/utils/libutils.a.p/utils.cpp.o',

benchmark/nixlbench/src/main.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
#include <iostream>
2020
#include <nixl.h>
2121
#include <sys/time.h>
22-
#include <gflags/gflags.h>
2322
#include "utils/utils.h"
2423
#include "utils/scope_guard.h"
2524
#include "worker/nixl/nixl_worker.h"
@@ -182,9 +181,7 @@ static std::unique_ptr<xferBenchWorker> createWorker(int *argc, char ***argv) {
182181
}
183182

184183
int main(int argc, char *argv[]) {
185-
gflags::ParseCommandLineFlags(&argc, &argv, true);
186-
187-
int ret = xferBenchConfig::loadFromFlags();
184+
int ret = xferBenchConfig::parseConfig(argc, argv);
188185
if (0 != ret) {
189186
return EXIT_FAILURE;
190187
}
@@ -236,7 +233,5 @@ int main(int argc, char *argv[]) {
236233
return EXIT_FAILURE;
237234
}
238235

239-
gflags::ShutDownCommandLineFlags();
240-
241236
return worker_ptr->signaled() ? EXIT_FAILURE : EXIT_SUCCESS;
242237
}

benchmark/nixlbench/src/utils/meson.build

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ utils_sources = [
2121

2222
utils_deps = [
2323
cuda_dep,
24-
gflags_dep,
2524
openmp_dep
2625
]
2726

benchmark/nixlbench/src/utils/utils.cpp

Lines changed: 73 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,42 @@
3535
#include "runtime/etcd/etcd_rt.h"
3636
#include "utils/utils.h"
3737

38+
enum xferBenchParamType
39+
{
40+
XBPT_STRING,
41+
XBPT_BOOL,
42+
XBPT_UINT64,
43+
XBPT_INT32,
44+
__XBPT_LAST
45+
};
46+
47+
struct xferBenchParamInfo
48+
{
49+
const char *name;
50+
const char *help;
51+
xferBenchParamType type;
52+
union {
53+
const char *str;
54+
bool b;
55+
uint64_t u64;
56+
int32_t i32;
57+
} def_value;
58+
};
59+
3860
// Define gflags params
3961
#define NB_ARG_STRING(param_name, def_val, help_text) \
40-
DEFINE_string(param_name, def_val, help_text);
62+
{ .name = # param_name, .help = help_text, .type = XBPT_STRING, .def_value = { .str = def_val } },
4163
#define NB_ARG_BOOL(param_name, def_val, help_text) \
42-
DEFINE_bool(param_name, def_val, help_text);
64+
{ .name = # param_name, .help = help_text, .type = XBPT_BOOL, .def_value = { .b = def_val } },
4365
#define NB_ARG_UINT64(param_name, def_val, help_text) \
44-
DEFINE_uint64(param_name, def_val, help_text);
66+
{ .name = # param_name, .help = help_text, .type = XBPT_UINT64, .def_value = { .u64 = def_val} },
4567
#define NB_ARG_INT32(param_name, def_val, help_text) \
46-
DEFINE_int32(param_name, def_val, help_text);
68+
{ .name = # param_name, .help = help_text, .type = XBPT_INT32, .def_value = { .i32 = def_val } },
4769

4870
/**********
4971
* xferBench Config
5072
**********/
73+
const xferBenchParamInfo xbench_params[] = {
5174
NB_ARG_STRING(benchmark_group, "default", \
5275
"Name of benchmark group. Use different names to run multiple benchmarks in parallel " \
5376
"(Default: default)")
@@ -135,6 +158,7 @@ NB_ARG_STRING(gusli_device_security, "", \
135158
"If empty or fewer than devices, uses 'sec=0x3' as default. " \
136159
"For GUSLI backend, use device_list in format 'id:type:path' where type is F (file) " \
137160
"or K (kernel device).")
161+
};
138162

139163
#undef NB_ARG_INT32
140164
#undef NB_ARG_UINT64
@@ -196,9 +220,52 @@ uint64_t xferBenchConfig::gusli_bdev_byte_offset = 0;
196220
std::string xferBenchConfig::gusli_device_security = "";
197221

198222
int
199-
xferBenchConfig::loadFromFlags() {
223+
xferBenchConfig::parseConfig(int argc, char *argv[])
224+
{
225+
cxxopts::Options options("nixlbench", "NIXL Benchmark Tool");
226+
227+
options.add_options()
228+
("help", "Print usage");
229+
230+
for (size_t i = 0; i < sizeof(xbench_params) / sizeof(xbench_params[0]); i++) {
231+
const xferBenchParamInfo *param = &xbench_params[i];
232+
233+
switch (param->type) {
234+
case XBPT_STRING:
235+
options.add_options()
236+
(param->name, param->help, cxxopts::value<std::string>()->default_value(param->def_value.str));
237+
break;
238+
case XBPT_BOOL:
239+
options.add_options()
240+
(param->name, param->help, cxxopts::value<bool>()->default_value(param->def_value.b ? "true" : "false"));
241+
break;
242+
case XBPT_UINT64:
243+
options.add_options()
244+
(param->name, param->help, cxxopts::value<uint64_t>()->default_value(std::to_string(param->def_value.u64)));
245+
break;
246+
case XBPT_INT32:
247+
options.add_options()
248+
(param->name, param->help, cxxopts::value<int32_t>()->default_value(std::to_string(param->def_value.i32)));
249+
break;
250+
default:
251+
std::cerr << param->name << ": unsupported param type: " << param->type << std::endl;
252+
return -1;
253+
}
254+
}
255+
256+
auto result = options.parse(argc, argv);
257+
if (result.count("help")) {
258+
std::cout << options.help() << std::endl;
259+
return -1;
260+
}
261+
262+
return loadParams(result);
263+
}
264+
265+
int
266+
xferBenchConfig::loadParams(cxxopts::ParseResult &result) {
200267
#define NB_ARG(name) \
201-
FLAGS_ ##name
268+
result[#name].as<decltype(name)>()
202269

203270
benchmark_group = NB_ARG(benchmark_group);
204271
runtime_type = NB_ARG(runtime_type);

benchmark/nixlbench/src/utils/utils.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <optional>
2929
#include <utils/common/nixl_time.h>
3030
#include "runtime/runtime.h"
31+
#include "utils/cxxopts.hpp"
3132

3233
#if HAVE_CUDA
3334
#include <cuda.h>
@@ -178,7 +179,7 @@ class xferBenchConfig {
178179
static std::string gusli_device_security;
179180

180181
static int
181-
loadFromFlags();
182+
parseConfig(int argc, char *argv[]);
182183
static void
183184
printConfig();
184185
static void
@@ -189,6 +190,10 @@ class xferBenchConfig {
189190
parseDeviceList();
190191
static bool
191192
isStorageBackend();
193+
194+
protected:
195+
static int
196+
loadParams(cxxopts::ParseResult &options);
192197
};
193198

194199
// Shared GUSLI device config used by utils and nixl_worker

benchmark/nixlbench/src/worker/meson.build

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ worker_sources = [
2020

2121
worker_deps = [
2222
cuda_dep,
23-
gflags_dep,
2423
openmp_dep,
2524
etcd_dep
2625
]

0 commit comments

Comments
 (0)