nvbench icon indicating copy to clipboard operation
nvbench copied to clipboard

Add example showing how to parse additional arguments

Open alliepiper opened this issue 2 years ago • 6 comments

Several users have asked about how to add custom arguments to their benchmarks (e.g. #86).

This is done by implementing an application specific main(argc, argv) function and linking to the nvbench::nvbench CMake target instead of nvbench::main. The custom main will need to parse out additional arguments, and then use the macros defined in main.cuh to parse the remaining args and run NVBench. Something like:

int main(int argc, char** argv)
{
  // parse custom args and remove them from (or rebuild) argc/argv here
  
  NVBENCH_MAIN_BODY(argc, argv);
}

A singleton or some global state is then needed to communicate the custom options to the benchmarks.

We should add an example that shows how to do this.

alliepiper avatar May 10 '22 19:05 alliepiper

I had to solve the same problem with using GBench a long time ago.

I found that when defining a custom main, GBench has a ::benchmark::Initialize(arg,argv) function that will strip out any of the command line arguments it recognizes and modify argc/argv accordingly.

See: https://github.com/rapidsai/rmm/blob/4e8bca57a8b7cbc46c05ded1fbb70b57f9042e75/benchmarks/replay/replay.cpp#L332-L334

Instead of making it the users responsibility to parse out custom args, I think it would be nice to do the opposite and have nvbench strip out the args it knows about and leave the rest.

jrhemstad avatar May 11 '22 00:05 jrhemstad

I agree -- this process could be made much more user friendly and we should definitely explore these sorts of conveniences. I'd still want to error out for unknown args when using the default main implementation, but I'm on-board with @jrhemstad's suggestion for user-defined main.

alliepiper avatar May 11 '22 16:05 alliepiper

FYI we were able to make it work (here's an example: https://github.com/gunrock/essentials/blob/d1f668cdb062b1c5ef442b1eef2a1cb0405e688f/benchmarks/mst_bench.cu). I'd be happy to add an example here as well. Thanks for your help @allisonvacanti !

annielytical avatar Jun 03 '22 20:06 annielytical

A PR with a simple example would definitely be welcome! I think we'll want to make some additional changes to NVBench to simplify this usecase, but having the current example will help highlight some of the rough edges.

alliepiper avatar Jun 06 '22 17:06 alliepiper

One potential interface for this would be to provide a new variant of the NVBENCH_MAIN macro, that allows default arguments to be specified along with a lambda for parsing custom args. Something like:

NVBENCH_MAIN_ARGS(
  {"-q", "--timeout", "60"}, // Prepended args
  [](nvbench::option_parser& parser)
  {
    for (arg : parser.get_unknown_args())
    {
      if (arg == "--custom_format")
      { // Ok, can't use range-for and get next_arg...
        parser.add_printer<custom_format>(next_arg);
      }
      else if (arg == "--validate")
      { // Benchmarks check this and optionally do validation:
        g_do_validation = true;
      }
    }
  });

alliepiper avatar Jan 05 '23 16:01 alliepiper

I was working on our main implementation recently, and added some nicer hooks for doing common things like parsing other options. Check this out to see if it gives you a better approach, the test files have examples: https://github.com/NVIDIA/nvbench/pull/165

I think there's still more work to do in this area that would involve cleaning up the argument parsing machinery and making it directly extensible, but these hooks should address simple cases.

alliepiper avatar Apr 07 '24 22:04 alliepiper