diff --git a/README.md b/README.md index a2e4b3a..ef61a23 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,24 @@ Unit tests for an individual file can be built and run with `make fft_fr_test` f Thanks to [Acutest](https://github.com/mity/acutest) for the unit test harness, which is used here under the MIT licence. +## Run benchmarks + +This will run all available benchmarks, for the default one second per test size: + +``` +cd src +make bench +``` + +You can run individual benchmarks, and optionally specify how long to run each test size: + +``` +make fft_fr_bench +./fft_fr_bench 5 +``` + +Doing `make clean` should resolve any weird build issues. + ## Prerequisites - Blst library (see above) diff --git a/src/Makefile b/src/Makefile index fa2de1a..b67685c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -41,4 +41,5 @@ clean: rm -f *.o rm -f libckzg.a rm -f $(TESTS) + rm -f $(BENCH) rm -f a.out diff --git a/src/bench_util.c b/src/bench_util.c index cb03b5e..46a20dd 100644 --- a/src/bench_util.c +++ b/src/bench_util.c @@ -18,7 +18,7 @@ #include "bench_util.h" #include "blst_util.h" -unsigned long tdiff(timespec start, timespec end) { +unsigned long tdiff(timespec_t start, timespec_t end) { return (end.tv_sec - start.tv_sec) * NANO + (end.tv_nsec - start.tv_nsec); } diff --git a/src/bench_util.h b/src/bench_util.h index 6c0e26e..797a2bb 100644 --- a/src/bench_util.h +++ b/src/bench_util.h @@ -17,11 +17,12 @@ #include // CLOCK_REALTIME, clock_gettime(), timespec #include "c_kzg.h" -typedef struct timespec timespec; +typedef struct timespec timespec_t; #define NANO 1000000000L +#define NSEC 1 -unsigned long tdiff(timespec start, timespec end); +unsigned long tdiff(timespec_t start, timespec_t end); uint64_t rand_uint64(); blst_fr rand_fr(); blst_p1 rand_g1(); diff --git a/src/fft_fr_bench.c b/src/fft_fr_bench.c index 3677ad2..e28dfa1 100644 --- a/src/fft_fr_bench.c +++ b/src/fft_fr_bench.c @@ -14,19 +14,21 @@ * limitations under the License. */ -#include // malloc(), free() +#include // malloc(), free(), atoi() #include // printf() #include // assert() +#include // EXIT_SUCCESS/FAILURE #include "bench_util.h" #include "fft_fr.h" // Run the benchmark for `max_seconds` and return the time per iteration in nanoseconds. long run_bench(int scale, int max_seconds) { - timespec t0, t1; + timespec_t t0, t1; unsigned long total_time = 0, nits = 0; FFTSettings fs; assert(C_KZG_OK == new_fft_settings(&fs, scale)); + // Allocate on the heap to avoid stack overflow for large sizes blst_fr *data, *out; data = malloc(fs.max_width * sizeof(blst_fr)); @@ -51,11 +53,29 @@ long run_bench(int scale, int max_seconds) { return total_time / nits; } -#define NSEC 1 +int main(int argc, char *argv[]) { + int nsec = 0; -int main(void) { - printf("*** Benchmarking FFT_fr, %d second%s per test.\n", NSEC, NSEC == 1 ? "" : "s"); - for (int scale = 4; scale < 16; scale++) { - printf("fft_fr/scale_%d %lu ns/op\n", scale, run_bench(scale, 1)); + switch (argc) { + case 1: + nsec = NSEC; + break; + case 2: + nsec = atoi(argv[1]); + break; + default: + break; + }; + + if (nsec == 0) { + printf("Usage: %s [test time in seconds > 0]\n", argv[0]); + exit(EXIT_FAILURE); } + + printf("*** Benchmarking FFT_fr, %d second%s per test.\n", nsec, nsec == 1 ? "" : "s"); + for (int scale = 4; scale <= 15; scale++) { + printf("fft_fr/scale_%d %lu ns/op\n", scale, run_bench(scale, nsec)); + } + + return EXIT_SUCCESS; } diff --git a/src/fft_g1_bench.c b/src/fft_g1_bench.c index ef6e7b9..6be5fc5 100644 --- a/src/fft_g1_bench.c +++ b/src/fft_g1_bench.c @@ -14,19 +14,21 @@ * limitations under the License. */ -#include // malloc(), free() +#include // malloc(), free(), atoi() #include // printf() #include // assert() +#include // EXIT_SUCCESS/FAILURE #include "bench_util.h" #include "fft_g1.h" // Run the benchmark for `max_seconds` and return the time per iteration in nanoseconds. long run_bench(int scale, int max_seconds) { - timespec t0, t1; + timespec_t t0, t1; unsigned long total_time = 0, nits = 0; FFTSettings fs; assert(C_KZG_OK == new_fft_settings(&fs, scale)); + // Allocate on the heap to avoid stack overflow for large sizes blst_p1 *data, *out; data = malloc(fs.max_width * sizeof(blst_p1)); @@ -51,11 +53,29 @@ long run_bench(int scale, int max_seconds) { return total_time / nits; } -#define NSEC 1 +int main(int argc, char *argv[]) { + int nsec = 0; -int main(void) { - printf("*** Benchmarking FFT_g1, %d second%s per test.\n", NSEC, NSEC == 1 ? "" : "s"); - for (int scale = 4; scale < 16; scale++) { - printf("fft_g1/scale_%d %lu ns/op\n", scale, run_bench(scale, 1)); + switch (argc) { + case 1: + nsec = NSEC; + break; + case 2: + nsec = atoi(argv[1]); + break; + default: + break; + }; + + if (nsec == 0) { + printf("Usage: %s [test time in seconds > 0]\n", argv[0]); + exit(EXIT_FAILURE); } + + printf("*** Benchmarking FFT_g1, %d second%s per test.\n", nsec, nsec == 1 ? "" : "s"); + for (int scale = 4; scale <= 15; scale++) { + printf("fft_g1/scale_%d %lu ns/op\n", scale, run_bench(scale, nsec)); + } + + return EXIT_SUCCESS; }