X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/bfa784e73f294ed9a40417bfbed3d3d2a76ca86b..272ccad1b68b6d9c17069f3c934886925bb15b5d:/src/xbt/parmap.c diff --git a/src/xbt/parmap.c b/src/xbt/parmap.c index fa073e8e2e..d163965fe5 100644 --- a/src/xbt/parmap.c +++ b/src/xbt/parmap.c @@ -12,6 +12,7 @@ #ifdef HAVE_FUTEX_H #include +#include #endif #include "xbt/parmap.h" @@ -346,7 +347,7 @@ static void xbt_parmap_posix_worker_wait(xbt_parmap_t parmap, unsigned round) { xbt_os_mutex_acquire(parmap->ready_mutex); /* wait for more work */ - if (parmap->work < round) { + if (parmap->work != round) { xbt_os_cond_wait(parmap->ready_cond, parmap->ready_mutex); } xbt_os_mutex_release(parmap->ready_mutex); @@ -383,7 +384,7 @@ static void xbt_parmap_futex_worker_signal(xbt_parmap_t parmap) unsigned count = __sync_add_and_fetch(&parmap->thread_counter, 1); if (count == parmap->num_workers) { /* all workers have finished, wake the controller */ - futex_wake(&parmap->thread_counter, 1); + futex_wake(&parmap->thread_counter, INT_MAX); } } @@ -399,7 +400,7 @@ static void xbt_parmap_futex_master_signal(xbt_parmap_t parmap) parmap->thread_counter = 1; __sync_add_and_fetch(&parmap->work, 1); /* wake all workers */ - futex_wake(&parmap->work, parmap->num_workers - 1); + futex_wake(&parmap->work, INT_MAX); } /** @@ -415,8 +416,10 @@ static void xbt_parmap_futex_worker_wait(xbt_parmap_t parmap, unsigned round) { unsigned work = parmap->work; /* wait for more work */ - if (work < round) + while (work != round) { futex_wait(&parmap->work, work); + work = parmap->work; + } } #endif @@ -471,7 +474,7 @@ static void xbt_parmap_busy_master_signal(xbt_parmap_t parmap) static void xbt_parmap_busy_worker_wait(xbt_parmap_t parmap, unsigned round) { /* wait for more work */ - while (parmap->work < round) { + while (parmap->work != round) { xbt_os_thread_yield(); } } @@ -479,43 +482,148 @@ static void xbt_parmap_busy_worker_wait(xbt_parmap_t parmap, unsigned round) #ifdef SIMGRID_TEST #include "xbt.h" #include "xbt/ex.h" +#include "xbt/xbt_os_thread.h" +#include "xbt/xbt_os_time.h" +#include "gras_config.h" /* HAVE_FUTEX_H */ XBT_TEST_SUITE("parmap", "Parallel Map"); XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(xbt_parmap_unit); -xbt_parmap_t parmap; +#ifdef HAVE_FUTEX_H +#define TEST_PARMAP_SKIP_TEST(mode) 0 +#else +#define TEST_PARMAP_SKIP_TEST(mode) ((mode) == XBT_PARMAP_FUTEX) +#endif -void fun(void *arg); +#define TEST_PARMAP_VALIDATE_MODE(mode) \ + if (TEST_PARMAP_SKIP_TEST(mode)) { xbt_test_skip(); return; } else ((void)0) -void fun(void *arg) +static void fun_double(void *arg) { - //XBT_INFO("I'm job %lu", (unsigned long)arg); + unsigned *u = arg; + *u = 2 * *u + 1; } -XBT_TEST_UNIT("basic", test_parmap_basic, "Basic usage") +/* Check that the computations are correctly done. */ +static void test_parmap_basic(e_xbt_parmap_mode_t mode) { - xbt_test_add("Create the parmap"); + unsigned num_workers; + + for (num_workers = 1 ; num_workers <= 16 ; num_workers *= 2) { + const unsigned len = 1033; + const unsigned num = 5; + unsigned *a; + xbt_dynar_t data; + xbt_parmap_t parmap; + unsigned i; + + xbt_test_add("Basic parmap usage (%u workers)", num_workers); + + TEST_PARMAP_VALIDATE_MODE(mode); + parmap = xbt_parmap_new(num_workers, mode); + + a = xbt_malloc(len * sizeof *a); + data = xbt_dynar_new(sizeof a, NULL); + for (i = 0; i < len; i++) { + a[i] = i; + xbt_dynar_push_as(data, void *, &a[i]); + } - unsigned long i, j; - xbt_dynar_t data = xbt_dynar_new(sizeof(void *), NULL); + for (i = 0; i < num; i++) + xbt_parmap_apply(parmap, fun_double, data); - /* Create the parallel map */ -#ifdef HAVE_FUTEX_H - parmap = xbt_parmap_new(10, XBT_PARMAP_FUTEX); -#else - parmap = xbt_parmap_new(10, XBT_PARMAP_BUSY_WAIT); -#endif - for (j = 0; j < 100; j++) { - xbt_dynar_push_as(data, void *, (void *)j); + for (i = 0; i < len; i++) { + unsigned expected = (1U << num) * (i + 1) - 1; + xbt_test_assert(a[i] == expected, + "a[%u]: expected %u, got %u", i, expected, a[i]); + } + + xbt_dynar_free(&data); + xbt_free(a); + xbt_parmap_destroy(parmap); } +} + +XBT_TEST_UNIT("basic_posix", test_parmap_basic_posix, "Basic usage: posix") +{ + test_parmap_basic(XBT_PARMAP_POSIX); +} + +XBT_TEST_UNIT("basic_futex", test_parmap_basic_futex, "Basic usage: futex") +{ + test_parmap_basic(XBT_PARMAP_FUTEX); +} - for (i = 0; i < 5; i++) { - xbt_parmap_apply(parmap, fun, data); +XBT_TEST_UNIT("basic_busy_wait", test_parmap_basic_busy_wait, "Basic usage: busy_wait") +{ + test_parmap_basic(XBT_PARMAP_BUSY_WAIT); +} + +static void fun_get_id(void *arg) +{ + *(uintptr_t *)arg = (uintptr_t)xbt_os_thread_self(); + xbt_os_sleep(0.5); +} + +static int fun_compare(const void *pa, const void *pb) +{ + uintptr_t a = *(uintptr_t *)pa; + uintptr_t b = *(uintptr_t *)pb; + return a < b ? -1 : a > b ? 1 : 0; +} + +/* Check that all threads are working. */ +static void test_parmap_extended(e_xbt_parmap_mode_t mode) +{ + unsigned num_workers; + + for (num_workers = 1 ; num_workers <= 16 ; num_workers *= 2) { + const unsigned len = 2 * num_workers; + uintptr_t *a; + xbt_parmap_t parmap; + xbt_dynar_t data; + unsigned i; + unsigned count; + + xbt_test_add("Extended parmap usage (%u workers)", num_workers); + + TEST_PARMAP_VALIDATE_MODE(mode); + parmap = xbt_parmap_new(num_workers, mode); + + a = xbt_malloc(len * sizeof *a); + data = xbt_dynar_new(sizeof a, NULL); + for (i = 0; i < len; i++) + xbt_dynar_push_as(data, void *, &a[i]); + + xbt_parmap_apply(parmap, fun_get_id, data); + + qsort(a, len, sizeof a[0], fun_compare); + count = 1; + for (i = 1; i < len; i++) + if (a[i] != a[i - 1]) + count++; + xbt_test_assert(count == num_workers, + "only %u/%u threads did some work", count, num_workers); + + xbt_dynar_free(&data); + xbt_free(a); + xbt_parmap_destroy(parmap); } +} + +XBT_TEST_UNIT("extended_posix", test_parmap_extended_posix, "Extended usage: posix") +{ + test_parmap_extended(XBT_PARMAP_POSIX); +} - /* Destroy the parmap */ - xbt_parmap_destroy(parmap); - xbt_dynar_free(&data); +XBT_TEST_UNIT("extended_futex", test_parmap_extended_futex, "Extended usage: futex") +{ + test_parmap_extended(XBT_PARMAP_FUTEX); +} + +XBT_TEST_UNIT("extended_busy_wait", test_parmap_extended_busy_wait, "Extended usage: busy_wait") +{ + test_parmap_extended(XBT_PARMAP_BUSY_WAIT); } #endif /* SIMGRID_TEST */