From: Arnaud Giersch Date: Thu, 3 Aug 2017 11:56:50 +0000 (+0200) Subject: Port parmap_bench to C++. X-Git-Tag: v3_17~266 X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/commitdiff_plain/fcd7ccb546f1381f883b7522b41bf47c63d745b3 Port parmap_bench to C++. --- diff --git a/teshsuite/xbt/CMakeLists.txt b/teshsuite/xbt/CMakeLists.txt index 42e89022b9..a8fd74320a 100644 --- a/teshsuite/xbt/CMakeLists.txt +++ b/teshsuite/xbt/CMakeLists.txt @@ -1,4 +1,4 @@ -foreach(x heap_bench log_large log_usage mallocator parallel_log_crashtest parmap_bench) +foreach(x heap_bench log_large log_usage mallocator parallel_log_crashtest) add_executable (${x} ${x}/${x}.c) target_link_libraries(${x} simgrid) set_target_properties(${x} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${x}) @@ -7,7 +7,7 @@ foreach(x heap_bench log_large log_usage mallocator parallel_log_crashtest parma set(teshsuite_src ${teshsuite_src} ${CMAKE_CURRENT_SOURCE_DIR}/${x}/${x}.c) endforeach() -foreach(x parmap_test) +foreach(x parmap_bench parmap_test) add_executable (${x} ${x}/${x}.cpp) target_link_libraries(${x} simgrid) set_target_properties(${x} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${x}) diff --git a/teshsuite/xbt/parmap_bench/parmap_bench.c b/teshsuite/xbt/parmap_bench/parmap_bench.c deleted file mode 100644 index 3944546a5b..0000000000 --- a/teshsuite/xbt/parmap_bench/parmap_bench.c +++ /dev/null @@ -1,204 +0,0 @@ -/* Copyright (c) 2012-2017. The SimGrid Team. All rights reserved. */ - -/* This program is free software; you can redistribute it and/or modify it - * under the terms of the license (GNU LGPL) which comes with this package. */ - -#include "simgrid/msg.h" -#include "src/internal_config.h" /* HAVE_FUTEX_H */ -#include "xbt/xbt_os_time.h" -#include -#include -#include -#include -#include - -#define MODES_DEFAULT 0x7 -#define TIMEOUT 10.0 -#define ARRAY_SIZE 10007 -#define FIBO_MAX 25 - -void (*fun_to_apply)(void *); - -static const char *parmap_mode_name(e_xbt_parmap_mode_t mode) -{ - static char name[80]; - switch (mode) { - case XBT_PARMAP_POSIX: - snprintf(name, sizeof name, "POSIX"); - break; - case XBT_PARMAP_FUTEX: - snprintf(name, sizeof name, "FUTEX"); - break; - case XBT_PARMAP_BUSY_WAIT: - snprintf(name, sizeof name, "BUSY_WAIT"); - break; - case XBT_PARMAP_DEFAULT: - snprintf(name, sizeof name, "DEFAULT"); - break; - default: - snprintf(name, sizeof name, "UNKNOWN(%d)", (int)mode); - break; - } - return name; -} - -static int parmap_skip_mode(e_xbt_parmap_mode_t mode) -{ -#if !HAVE_FUTEX_H - if (mode == XBT_PARMAP_FUTEX) { - printf("not available\n"); - return 1; - } else -#endif - return 0; -} - -static unsigned fibonacci(unsigned n) -{ - if (n < 2) - return n; - else - return fibonacci(n - 1) + fibonacci(n - 2); -} - -static void fun_small_comp(void *arg) -{ - unsigned *u = arg; - *u = 2 * *u + 1; -} - -static void fun_big_comp(void *arg) -{ - unsigned *u = arg; - *u = fibonacci(*u % FIBO_MAX); -} - -static void array_new(unsigned **a, xbt_dynar_t *data) -{ - *a = xbt_malloc(ARRAY_SIZE * sizeof **a); - *data = xbt_dynar_new(sizeof *a, NULL); - xbt_dynar_shrink(*data, ARRAY_SIZE); - for (int i = 0 ; i < ARRAY_SIZE ; i++) { - (*a)[i] = i; - xbt_dynar_push_as(*data, void*, &(*a)[i]); - } -} - -static void bench_parmap_full(int nthreads, e_xbt_parmap_mode_t mode) -{ - unsigned *a; - xbt_dynar_t data; - xbt_parmap_t parmap; - double elapsed_time; - - printf("** mode = %-15s ", parmap_mode_name(mode)); - fflush(stdout); - - if (parmap_skip_mode(mode)) - return; - - array_new(&a, &data); - - int i = 0; - double start_time = xbt_os_time(); - do { - parmap = xbt_parmap_new(nthreads, mode); - xbt_parmap_apply(parmap, fun_to_apply, data); - xbt_parmap_destroy(parmap); - elapsed_time = xbt_os_time() - start_time; - i++; - } while (elapsed_time < TIMEOUT); - - printf("ran %d times in %g seconds (%g/s)\n", i, elapsed_time, i / elapsed_time); - - xbt_dynar_free(&data); - xbt_free(a); -} - -static void bench_parmap_apply(int nthreads, e_xbt_parmap_mode_t mode) -{ - unsigned *a; - xbt_dynar_t data; - double elapsed_time; - - printf("** mode = %-15s ", parmap_mode_name(mode)); - fflush(stdout); - - if (parmap_skip_mode(mode)) - return; - - array_new(&a, &data); - - xbt_parmap_t parmap = xbt_parmap_new(nthreads, mode); - int i = 0; - double start_time = xbt_os_time(); - do { - xbt_parmap_apply(parmap, fun_to_apply, data); - elapsed_time = xbt_os_time() - start_time; - i++; - } while (elapsed_time < TIMEOUT); - xbt_parmap_destroy(parmap); - - printf("ran %d times in %g seconds (%g/s)\n", i, elapsed_time, i / elapsed_time); - - xbt_dynar_free(&data); - xbt_free(a); -} - -static void bench_all_modes(void (*bench_fun)(int, e_xbt_parmap_mode_t), - int nthreads, unsigned modes) -{ - e_xbt_parmap_mode_t all_modes[] = {XBT_PARMAP_POSIX, XBT_PARMAP_FUTEX, XBT_PARMAP_BUSY_WAIT, XBT_PARMAP_DEFAULT}; - - for (unsigned i = 0 ; i < sizeof all_modes / sizeof all_modes[0] ; i++) { - if (1U << i & modes) - bench_fun(nthreads, all_modes[i]); - } -} - -int main(int argc, char *argv[]) -{ - int nthreads; - unsigned modes = MODES_DEFAULT; - - MSG_init(&argc, argv); - - if (argc != 2 && argc != 3) { - fprintf(stderr, "Usage: %s nthreads [modes]\n" - " nthreads - number of working threads\n" - " modes - bitmask of modes to test\n", - argv[0]); - return EXIT_FAILURE; - } - nthreads = atoi(argv[1]); - if (nthreads < 1) { - fprintf(stderr, "ERROR: invalid thread count: %d\n", nthreads); - return EXIT_FAILURE; - } - if (argc == 3) - modes = strtol(argv[2], NULL, 0); - - printf("Parmap benchmark with %d workers (modes = %#x)...\n\n", nthreads, modes); - - fun_to_apply = &fun_small_comp; - - printf("Benchmark for parmap create+apply+destroy (small comp):\n"); - bench_all_modes(bench_parmap_full, nthreads, modes); - printf("\n"); - - printf("Benchmark for parmap apply only (small comp):\n"); - bench_all_modes(bench_parmap_apply, nthreads, modes); - printf("\n"); - - fun_to_apply = &fun_big_comp; - - printf("Benchmark for parmap create+apply+destroy (big comp):\n"); - bench_all_modes(bench_parmap_full, nthreads, modes); - printf("\n"); - - printf("Benchmark for parmap apply only (big comp):\n"); - bench_all_modes(bench_parmap_apply, nthreads, modes); - printf("\n"); - - return EXIT_SUCCESS; -} diff --git a/teshsuite/xbt/parmap_bench/parmap_bench.cpp b/teshsuite/xbt/parmap_bench/parmap_bench.cpp new file mode 100644 index 0000000000..f7d0fcce86 --- /dev/null +++ b/teshsuite/xbt/parmap_bench/parmap_bench.cpp @@ -0,0 +1,187 @@ +/* Copyright (c) 2012-2017. The SimGrid Team. All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#include "src/internal_config.h" // HAVE_FUTEX_H +#include +#include +#include + +#include +#include +#include +#include // std::iota +#include +#include + +#define MODES_DEFAULT 0x7 +#define TIMEOUT 10.0 +#define ARRAY_SIZE 10007 +#define FIBO_MAX 25 + +void (*fun_to_apply)(unsigned*); + +static std::string parmap_mode_name(e_xbt_parmap_mode_t mode) +{ + std::string name; + switch (mode) { + case XBT_PARMAP_POSIX: + name = "POSIX"; + break; + case XBT_PARMAP_FUTEX: + name = "FUTEX"; + break; + case XBT_PARMAP_BUSY_WAIT: + name = "BUSY_WAIT"; + break; + case XBT_PARMAP_DEFAULT: + name = "DEFAULT"; + break; + default: + name = "UNKNOWN(" + std::to_string(mode) + ")"; + break; + } + return name; +} + +static bool parmap_skip_mode(e_xbt_parmap_mode_t mode) +{ +#if !HAVE_FUTEX_H + if (mode == XBT_PARMAP_FUTEX) { + std::cout << "not available\n"; + return true; + } else +#endif + return false; +} + +static unsigned fibonacci(unsigned n) +{ + if (n < 2) + return n; + else + return fibonacci(n - 1) + fibonacci(n - 2); +} + +static void fun_small_comp(unsigned* arg) +{ + *arg = 2 * *arg + 1; +} + +static void fun_big_comp(unsigned* arg) +{ + *arg = fibonacci(*arg % FIBO_MAX); +} + +static void bench_parmap_full(int nthreads, e_xbt_parmap_mode_t mode) +{ + std::cout << "** mode = " << std::left << std::setw(15) << parmap_mode_name(mode) << " "; + std::cout.flush(); + + if (parmap_skip_mode(mode)) + return; + + std::vector a(ARRAY_SIZE); + std::vector data(ARRAY_SIZE); + std::iota(begin(a), end(a), 0); + std::iota(begin(data), end(data), &a[0]); + + int i = 0; + double start_time = xbt_os_time(); + double elapsed_time; + do { + { + simgrid::xbt::Parmap parmap(nthreads, mode); + parmap.apply(fun_to_apply, data); + } // enclosing block to ensure that the parmap is destroyed here. + elapsed_time = xbt_os_time() - start_time; + i++; + } while (elapsed_time < TIMEOUT); + + std::cout << "ran " << i << " times in " << elapsed_time << " seconds (" << (i / elapsed_time) << "/s)\n"; +} + +static void bench_parmap_apply(int nthreads, e_xbt_parmap_mode_t mode) +{ + std::cout << "** mode = " << std::left << std::setw(15) << parmap_mode_name(mode) << " "; + std::cout.flush(); + + if (parmap_skip_mode(mode)) + return; + + std::vector a(ARRAY_SIZE); + std::vector data(ARRAY_SIZE); + std::iota(begin(a), end(a), 0); + std::iota(begin(data), end(data), &a[0]); + + simgrid::xbt::Parmap parmap(nthreads, mode); + int i = 0; + double start_time = xbt_os_time(); + double elapsed_time; + do { + parmap.apply(fun_to_apply, data); + elapsed_time = xbt_os_time() - start_time; + i++; + } while (elapsed_time < TIMEOUT); + + std::cout << "ran " << i << " times in " << elapsed_time << " seconds (" << (i / elapsed_time) << "/s)\n"; +} + +static void bench_all_modes(void (*bench_fun)(int, e_xbt_parmap_mode_t), int nthreads, unsigned modes) +{ + std::vector all_modes = {XBT_PARMAP_POSIX, XBT_PARMAP_FUTEX, XBT_PARMAP_BUSY_WAIT, + XBT_PARMAP_DEFAULT}; + + for (unsigned i = 0; i < all_modes.size(); i++) { + if (1U << i & modes) + bench_fun(nthreads, all_modes[i]); + } +} + +int main(int argc, char* argv[]) +{ + int nthreads; + unsigned modes = MODES_DEFAULT; + + MSG_init(&argc, argv); + + if (argc != 2 && argc != 3) { + std::cerr << "Usage: " << argv[0] << " nthreads [modes]\n" + << " nthreads - number of working threads\n" + << " modes - bitmask of modes to test\n"; + return EXIT_FAILURE; + } + nthreads = atoi(argv[1]); + if (nthreads < 1) { + std::cerr << "ERROR: invalid thread count: " << nthreads << "\n"; + return EXIT_FAILURE; + } + if (argc == 3) + modes = strtol(argv[2], NULL, 0); + + std::cout << "Parmap benchmark with " << nthreads << " workers (modes = " << std::hex << modes << std::dec + << ")...\n\n"; + + fun_to_apply = &fun_small_comp; + + std::cout << "Benchmark for parmap create+apply+destroy (small comp):\n"; + bench_all_modes(bench_parmap_full, nthreads, modes); + std::cout << std::endl; + + std::cout << "Benchmark for parmap apply only (small comp):\n"; + bench_all_modes(bench_parmap_apply, nthreads, modes); + std::cout << std::endl; + + fun_to_apply = &fun_big_comp; + + std::cout << "Benchmark for parmap create+apply+destroy (big comp):\n"; + bench_all_modes(bench_parmap_full, nthreads, modes); + std::cout << std::endl; + + std::cout << "Benchmark for parmap apply only (big comp):\n"; + bench_all_modes(bench_parmap_apply, nthreads, modes); + std::cout << std::endl; + + return EXIT_SUCCESS; +}