void thread_func(void *arg) { ABT_thread my_handle; ABT_thread_state my_state; ABT_thread_self(&my_handle); ABT_thread_get_state(my_handle, &my_state); if (my_state != ABT_THREAD_STATE_RUNNING) { fprintf(stderr, "ERROR: not in the RUNNUNG state\n"); } ABT_thread_release(my_handle); thread_arg_t *t_arg = (thread_arg_t *)arg; ABT_thread next; ABT_test_printf(1, "[TH%d]: before yield\n", t_arg->id); next = pick_one(t_arg->threads, t_arg->num_threads); ABT_thread_yield_to(next); ABT_test_printf(1, "[TH%d]: doing something ...\n", t_arg->id); next = pick_one(t_arg->threads, t_arg->num_threads); ABT_thread_yield_to(next); ABT_test_printf(1, "[TH%d]: after yield\n", t_arg->id); ABT_task task; ABT_task_self(&task); if (task != ABT_TASK_NULL) { fprintf(stderr, "ERROR: should not be tasklet\n"); } }
static void thread_hello(void *arg) { int old_rank, cur_rank; ABT_thread self; ABT_thread_id id; char *msg; ABT_xstream_self_rank(&cur_rank); ABT_thread_self(&self); ABT_thread_get_id(self, &id); ABT_thread_release(self); test_printf("[U%lu:E%d] Hello, world!\n", id, cur_rank); ABT_thread_yield(); old_rank = cur_rank; ABT_xstream_self_rank(&cur_rank); msg = (cur_rank == old_rank) ? "" : " (stolen)"; test_printf("[U%lu:E%d] Hello again #1.%s\n", id, cur_rank, msg); ABT_thread_yield(); old_rank = cur_rank; ABT_xstream_self_rank(&cur_rank); msg = (cur_rank == old_rank) ? "" : " (stolen)"; test_printf("[U%lu:E%d] Hello again #2.%s\n", id, cur_rank, msg); ABT_thread_yield(); old_rank = cur_rank; ABT_xstream_self_rank(&cur_rank); msg = (cur_rank == old_rank) ? "" : " (stolen)"; test_printf("[U%lu:E%d] Goodbye, world!%s\n", id, cur_rank, msg); }
void thread_func_migrate_to_xstream(void *arg) { arg_t *my_arg = (arg_t *)arg; int eid = my_arg->eid; ABT_xstream cur_xstream, tar_xstream; ABT_thread self; int i, next; ABT_thread_self(&self); for (i = 0; i < iter; i++) { next = (eid + 1) % num_xstreams; tar_xstream = g_xstreams[next]; ABT_thread_migrate_to_xstream(self, tar_xstream); while (1) { ABT_bool flag; ABT_xstream_self(&cur_xstream); ABT_xstream_equal(cur_xstream, tar_xstream, &flag); if (flag == ABT_TRUE) { break; } ABT_thread_yield(); } eid = next; } }
void thread_create(void *arg) { int rank, i, ret; ABT_thread self; ABT_thread_id id; ABT_pool my_pool; ABT_thread *threads; assert((size_t)arg == 0); ret = ABT_xstream_self_rank(&rank); ABT_TEST_ERROR(ret, "ABT_xstream_self_rank"); ret = ABT_thread_self(&self); ABT_TEST_ERROR(ret, "ABT_thread_self"); ret = ABT_thread_get_id(self, &id); ABT_TEST_ERROR(ret, "ABT_thread_get_id"); ret = ABT_thread_get_last_pool(self, &my_pool); ABT_TEST_ERROR(ret, "ABT_thread_get_last_pool"); threads = (ABT_thread *)malloc(num_threads * sizeof(ABT_thread)); /* Create ULTs */ for (i = 0; i < num_threads; i++) { ret = ABT_thread_create(my_pool, thread_func, (void *)1, ABT_THREAD_ATTR_NULL, &threads[i]); ABT_TEST_ERROR(ret, "ABT_thread_create"); } ABT_test_printf(1, "[U%lu:E%u]: created %d ULTs\n", id, rank, num_threads); /* Join ULTs */ for (i = 0; i < num_threads; i++) { ret = ABT_thread_join(threads[i]); ABT_TEST_ERROR(ret, "ABT_thread_join"); } ABT_test_printf(1, "[U%lu:E%u]: joined %d ULTs\n", id, rank, num_threads); /* Revive ULTs with a different function */ for (i = 0; i < num_threads; i++) { ret = ABT_thread_revive(my_pool, thread_func2, (void *)2, &threads[i]); ABT_TEST_ERROR(ret, "ABT_thread_revive"); } ABT_test_printf(1, "[U%lu:E%u]: revived %d ULTs\n", id, rank, num_threads); /* Join and free ULTs */ for (i = 0; i < num_threads; i++) { ret = ABT_thread_free(&threads[i]); ABT_TEST_ERROR(ret, "ABT_thread_free"); } ABT_test_printf(1, "[U%lu:E%u]: freed %d ULTs\n", id, rank, num_threads); free(threads); }
void task_func2(void *arg) { ABT_thread thread; ABT_thread_self(&thread); if (thread != ABT_THREAD_NULL) { fprintf(stderr, "ERROR: should not be ULT\n"); } size_t i; task_arg_t *my_arg = (task_arg_t *)arg; unsigned long long result = 1; for (i = 2; i <= my_arg->num; i++) { result += i; } my_arg->result = result; }
void thread_func2(void *arg) { int rank, ret; ABT_thread self; ABT_thread_id id; assert((size_t)arg == 2); ret = ABT_xstream_self_rank(&rank); ABT_TEST_ERROR(ret, "ABT_xstream_self_rank"); ret = ABT_thread_self(&self); ABT_TEST_ERROR(ret, "ABT_thread_self"); ret = ABT_thread_get_id(self, &id); ABT_TEST_ERROR(ret, "ABT_thread_get_id"); ABT_test_printf(1, "[U%lu:E%u]: Good-bye, world!\n", id, rank); }
void thread_recv_func(void *arg) { ABT_thread ult_self__; ABT_thread_self(&ult_self__); size_t my_id = (size_t) arg; if (verbose) printf("[rank %d, TH%lu]: receive\n", rank, my_id); int i, j; for (i = 0; i < num_loop; i++) { for (j = 1; j < size; j++) { int source = (rank + size - j) % size; if (verbose) printf("[rank %d, TH%lu]: MPI_Recv from %d\n", rank, my_id, source); MPI_Recv(recv_buf, buf_size, MPI_INT, source, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); sum += recv_buf[0]; } } }
void thread_send_func(void *arg) { ABT_thread ult_self__; ABT_thread_self(&ult_self__); size_t my_id = (size_t) arg; if (verbose) printf("[rank %d, TH%lu]: send\n", rank, my_id); int i, j; for (i = 0; i < num_loop; i++) { for (j = 1; j < size; j++) { int dest = (rank + j) % size; send_buf[0] = rank; if (verbose) printf("[rank %d, TH%lu]: MPI_Send to %d\n", rank, my_id, dest); MPI_Send(send_buf, buf_size, MPI_INT, dest, 0, MPI_COMM_WORLD); } } }
void rt1_launcher(void *arg) { int idx = (int)(intptr_t)arg; ABT_thread cur_thread; ABT_pool cur_pool; ABT_sched_config config; ABT_sched sched; size_t size; double t_start, t_end; ABT_sched_config_var cv_event_freq = { .idx = 0, .type = ABT_SCHED_CONFIG_INT }; ABT_sched_config_var cv_idx = { .idx = 1, .type = ABT_SCHED_CONFIG_INT }; ABT_sched_def sched_def = { .type = ABT_SCHED_TYPE_ULT, .init = sched_init, .run = sched_run, .free = sched_free, .get_migr_pool = NULL }; /* Create a scheduler */ ABT_sched_config_create(&config, cv_event_freq, 10, cv_idx, idx, ABT_sched_config_var_end); ABT_sched_create(&sched_def, 1, &rt1_data->pool, config, &sched); /* Push the scheduler to the current pool */ ABT_thread_self(&cur_thread); ABT_thread_get_last_pool(cur_thread, &cur_pool); ABT_pool_add_sched(cur_pool, sched); /* Free */ ABT_sched_config_free(&config); t_start = ABT_get_wtime(); while (1) { rt1_app(idx); ABT_pool_get_total_size(cur_pool, &size); if (size == 0) { ABT_sched_free(&sched); int rank; ABT_xstream_self_rank(&rank); printf("ES%d: finished\n", rank); ABT_mutex_lock(rt1_data->mutex); rt1_data->xstreams[rank] = ABT_XSTREAM_NULL; rt1_data->num_xstreams--; ABT_mutex_unlock(rt1_data->mutex); break; } t_end = ABT_get_wtime(); if ((t_end - t_start) > g_timeout) { ABT_sched_finish(sched); } } } static void rt1_app(int eid) { int i, num_comps; size_t size; ABT_thread cur_thread; ABT_pool cur_pool; ABT_thread_self(&cur_thread); ABT_thread_get_last_pool(cur_thread, &cur_pool); if (eid == 0) ABT_event_prof_start(); num_comps = rt1_data->num_comps; for (i = 0; i < num_comps * 2; i += 2) { ABT_thread_create(rt1_data->pool, rt1_app_compute, (void *)(intptr_t)(eid * num_comps * 2 + i), ABT_THREAD_ATTR_NULL, NULL); ABT_task_create(rt1_data->pool, rt1_app_compute, (void *)(intptr_t)(eid * num_comps * 2 + i + 1), NULL); } do { ABT_thread_yield(); /* If the size of cur_pool is zero, it means the stacked scheduler has * been terminated because of the shrinking event. */ ABT_pool_get_total_size(cur_pool, &size); if (size == 0) break; ABT_pool_get_total_size(rt1_data->pool, &size); } while (size > 0); if (eid == 0) { ABT_event_prof_stop(); int cnt = __atomic_exchange_n(&rt1_data->cnt, 0, __ATOMIC_SEQ_CST); double local_work = (double)(cnt * rt1_data->num_iters); ABT_event_prof_publish("ops", local_work, local_work); } } static void rt1_app_compute(void *arg) { int pos = (int)(intptr_t)arg; int i; rt1_data->app_data[pos] = 0; for (i = 0; i < rt1_data->num_iters; i++) { rt1_data->app_data[pos] += sin((double)pos); } __atomic_fetch_add(&rt1_data->cnt, 1, __ATOMIC_SEQ_CST); }
/* Create a work-stealing scheduler and push it to the pool */ static void thread_add_sched(void *arg) { int idx = (int)(intptr_t)arg; int i; ABT_thread cur_thread; ABT_pool cur_pool; ABT_pool *my_pools; ABT_sched_config config; ABT_sched sched; size_t size; double t_start, t_end; ABT_sched_config_var cv_event_freq = { .idx = 0, .type = ABT_SCHED_CONFIG_INT }; ABT_sched_config_var cv_idx = { .idx = 1, .type = ABT_SCHED_CONFIG_INT }; ABT_sched_def sched_def = { .type = ABT_SCHED_TYPE_ULT, .init = sched_init, .run = sched_run, .free = sched_free, .get_migr_pool = NULL }; /* Create a scheduler */ ABT_sched_config_create(&config, cv_event_freq, 10, cv_idx, idx, ABT_sched_config_var_end); my_pools = (ABT_pool *)malloc(sizeof(ABT_pool) * max_xstreams); for (i = 0; i < max_xstreams; i++) { my_pools[i] = g_pools[(idx + i) % max_xstreams]; } ABT_sched_create(&sched_def, max_xstreams, my_pools, config, &sched); /* Create a ULT for the new scheduler */ ABT_thread_create(my_pools[0], thread_work, arg, ABT_THREAD_ATTR_NULL, NULL); /* Push the scheduler to the current pool */ ABT_thread_self(&cur_thread); ABT_thread_get_last_pool(cur_thread, &cur_pool); ABT_pool_add_sched(cur_pool, sched); /* Free */ ABT_thread_release(cur_thread); ABT_sched_config_free(&config); free(my_pools); t_start = ABT_get_wtime(); while (1) { ABT_thread_yield(); ABT_pool_get_total_size(cur_pool, &size); if (size == 0) { ABT_sched_free(&sched); break; } t_end = ABT_get_wtime(); if ((t_end - t_start) > g_timeout) { ABT_sched_finish(sched); } } } static void thread_work(void *arg) { int idx = (int)(intptr_t)arg; int i; ABT_thread cur_thread; ABT_pool cur_pool; ABT_thread *threads; int num_threads; double t_start, t_end; ABT_thread_self(&cur_thread); ABT_thread_get_last_pool(cur_thread, &cur_pool); ABT_thread_release(cur_thread); t_start = ABT_get_wtime(); while (1) { num_threads = 2; threads = (ABT_thread *)malloc(sizeof(ABT_thread) * num_threads); for (i = 0; i < num_threads; i++) { ABT_thread_create(cur_pool, thread_hello, NULL, ABT_THREAD_ATTR_NULL, &threads[i]); } for (i = 0; i < num_threads; i++) { ABT_thread_free(&threads[i]); } free(threads); if (g_signal[idx]) { ABT_xstream xstream; ABT_xstream_self(&xstream); ABT_xstream_cancel(xstream); g_signal[idx] = 0; break; } t_end = ABT_get_wtime(); if ((t_end - t_start) > g_timeout) { break; } } } static void test_printf(const char *format, ...) { #if 0 va_start(list, format); vprintf(format, list); va_end(list); fflush(stdout); #endif }