diff --git a/Makefile b/Makefile index 1f0a786dff2c4fa19545dbbb20d951806a921edb..0ce8ec866c20d5226e794fb335b235ee5aee3d49 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,8 @@ CFLAGS=-O3 -fompss-2 BENCHMARKS=\ sched_get \ sched_add \ - register_deps + register_deps \ + readywave BIN=$(addprefix bench6.,$(BENCHMARKS)) DATA=$(addsuffix .csv, $(addprefix data/,$(BENCHMARKS))) diff --git a/README.md b/README.md index 68e6f47effb812cfa707b00b56ab96c67d56da5b..7ed7f9b8ead7630f1f3088961d0ae5adfeaab451 100644 --- a/README.md +++ b/README.md @@ -11,3 +11,5 @@ Examples: + + diff --git a/examples/readywave-instr.csv.png b/examples/readywave-instr.csv.png new file mode 100644 index 0000000000000000000000000000000000000000..c6747d395f6957b6773447d07daf1fe2850eb0ee Binary files /dev/null and b/examples/readywave-instr.csv.png differ diff --git a/plot/readywave.R b/plot/readywave.R new file mode 100644 index 0000000000000000000000000000000000000000..2f937f8cefed1f86260315fcd18799e804c551a4 --- /dev/null +++ b/plot/readywave.R @@ -0,0 +1,26 @@ +library(ggplot2) +library(dplyr, warn.conflicts = FALSE) +library(scales) +library(jsonlite) +library(readr) + +# Load the arguments (argv) +args = commandArgs(trailingOnly=TRUE) + +input_file = args[1] + +df = read_delim(input_file, delim=",", show_col_types = FALSE) + +dpi = 96 +h = 2 +w = 6 + +# --------------------------------------------------------------------- + +p = ggplot(df, aes(time_ms)) + + geom_histogram(bins=80) + + theme_bw() + + labs(x = "Time (ms)", title="Nanos6: readywave time") + # TODO: Add ntasks and taskwork to labels + +ggsave(sprintf("%s.png", input_file), plot=p, width=w, height=h, dpi=dpi) diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000000000000000000000000000000000000..c04b746b378ad21c79f74f00c802e5e7bf272187 --- /dev/null +++ b/shell.nix @@ -0,0 +1,15 @@ +let + pkgs = import (builtins.fetchTarball + "https://pm.bsc.es/gitlab/rarias/bscpkgs/-/archive/master/bscpkgs-master.tar.gz"); + + rWrapper = pkgs.rWrapper.override { + packages = with pkgs.rPackages; [ tidyverse rjson jsonlite egg viridis ]; + }; +in + pkgs.mkShell { + nativeBuildInputs = [ + pkgs.bsc.clangOmpss2 + pkgs.bsc.nanos6 + rWrapper + ]; + } diff --git a/src/readywave.c b/src/readywave.c new file mode 100644 index 0000000000000000000000000000000000000000..bec436c073e208d8f05591e0db0dc7227b6c6a08 --- /dev/null +++ b/src/readywave.c @@ -0,0 +1,116 @@ +/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC) + * SPDX-License-Identifier: GPL-3.0-or-later */ + +#define _DEFAULT_SOURCE + +#include "bench6.h" + +#include +#include +#include +#include +#include +#include + +static int ncpus = -1; +static long nruns = 100L; +static long ntasks_per_cpu = 5000L; +static double taskwork_us = 10.0; + +static double t0; + +#define M_WORK 10000000L + +static void +busywork(long loops) +{ + for (volatile long j = 0; j < loops; j++); +} + +static void +dummy_work(double ms) +{ + double end = get_time() + ms * 1e-3; + while (get_time() < end); +} + +static void +do_run(int run) +{ + /* Warm up all the threads */ + for (long i = 0L; i < ncpus; i++) { + #pragma oss task label("warmup") + dummy_work(20.0); + } + + #pragma oss taskwait + + int flag = 0; + + /* Delay task start so we can create lots of tasks */ + #pragma oss task inout(flag) label("trigger") + { + dummy_work(10.0); + busywork(M_WORK); /* So we can see it in perf */ + t0 = get_time(); + } + + for (long i = 0L; i < ntasks_per_cpu * ncpus; i++) { + #pragma oss task in(flag) label("quickie") + dummy_work(taskwork_us * 1e-3); + } + + /* When trigger finishes all small tasks will become ready */ + #pragma oss taskwait + double t1 = get_time(); + printf("%d,%ld,%d,%.3f,%.3f\n", run, ntasks_per_cpu, ncpus, taskwork_us, (t1 - t0) * 1e3); +} + +static int +usage(char *argv[]) +{ + fprintf(stderr, "Bench6: A set of Nanos6 micro-benchmarks\n"); + fprintf(stderr, "Usage: %s [-r NRUNS] [-t NTASKS_PER_CPU] [-w TASKWORK_US]\n", argv[0]); + fprintf(stderr, "\n"); + fprintf(stderr, +"Creates NTASKS_PER_CPU tasks per CPU that become ready at the\n" +"same time, like a wave. The time between the moment they become\n" +"ready and when the all end is measured. Tasks run for TASKWORK_US\n" +"microseconds. The test is repeated NRUNS times.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Defaults: NRUNS=%ld NTASKS_PER_CPU=%ld TASKWORK_US=%.3f\n", + nruns, ntasks_per_cpu, taskwork_us); + + return -1; +} + +int +main(int argc, char *argv[]) +{ + int opt; + + while ((opt = getopt(argc, argv, "hr:t:w:")) != -1) { + switch (opt) { + case 'r': + nruns = atol(optarg); + break; + case 't': + ntasks_per_cpu = atol(optarg); + break; + case 'w': + taskwork_us = atof(optarg); + break; + case 'h': /* Fall through */ + default: /* '?' */ + return usage(argv); + } + } + + ncpus = get_ncpus(); + + printf("%s,%s,%s,%s,%s\n", "run", "ntasks_per_cpu", "ncpus", "taskwork_us", "time_ms"); + for (int run = 0; run < nruns; run++) + do_run(run); + + return 0; +}