void rust_port_selector::select(rust_task *task, rust_port **dptr, rust_port **ports, size_t n_ports, uintptr_t *yield) { I(task->thread, this->ports == NULL); I(task->thread, this->n_ports == 0); I(task->thread, dptr != NULL); I(task->thread, ports != NULL); I(task->thread, n_ports != 0); I(task->thread, yield != NULL); *yield = false; size_t locks_taken = 0; bool found_msg = false; // Take each port's lock as we iterate through them because // if none of them contain a usable message then we need to // block the task before any of them can try to send another // message. // Start looking for ports from a different index each time. size_t j = isaac_rand(&task->thread->rctx); for (size_t i = 0; i < n_ports; i++) { size_t k = (i + j) % n_ports; rust_port *port = ports[k]; I(task->thread, port != NULL); port->lock.lock(); locks_taken++; if (port->buffer.size() > 0) { *dptr = port; found_msg = true; break; } } if (!found_msg) { this->ports = ports; this->n_ports = n_ports; I(task->thread, task->rendezvous_ptr == NULL); task->rendezvous_ptr = (uintptr_t*)dptr; task->block(this, "waiting for select rendezvous"); // Blocking the task might fail if the task has already been // killed, but in the event of both failure and success the // task needs to yield. On success, it yields and waits to be // unblocked. On failure it yields and is then fails the task. *yield = true; } for (size_t i = 0; i < locks_taken; i++) { size_t k = (i + j) % n_ports; rust_port *port = ports[k]; port->lock.unlock(); } }
rust_task * rust_scheduler::create_task(rust_task *spawner, const char *name, size_t init_stack_sz) { size_t thread_no; { scoped_lock with(lock); thread_no = isaac_rand(&rctx) % num_threads; live_tasks++; } rust_task_thread *thread = threads[thread_no]; return thread->create_task(spawner, name, init_stack_sz); }
/* * generate a random number */ ulong TadsServerManager::rand() { /* ISAAC needs protection against multi-threaded access */ mutex->lock(); /* get a random number */ ulong r = isaac_rand(ic); /* done with the mutex */ mutex->unlock(); /* return the number */ return r; }
/** * Schedules a running task for execution. Only running tasks can be * activated. Blocked tasks have to be unblocked before they can be * activated. * * Returns NULL if no tasks can be scheduled. */ rust_task * rust_task_thread::schedule_task() { I(this, this); // FIXME: in the face of failing tasks, this is not always right. // I(this, n_live_tasks() > 0); if (running_tasks.length() > 0) { size_t k = isaac_rand(&rctx); // Look around for a runnable task, starting at k. for(size_t j = 0; j < running_tasks.length(); ++j) { size_t i = (j + k) % running_tasks.length(); return (rust_task *)running_tasks[i]; } } return NULL; }
extern "C" CDECL size_t rand_next(randctx *rctx) { return isaac_rand(rctx); }
int main(int argc, const char *argv[]) { unsigned int i,j; unsigned long int elapsed_time; unsigned long int times[10]; double mean, var; struct timespec tp1, tp2; printf("#======================================#\n"); printf("| Speed tests for the generators |\n"); printf("#======================================#\n"); printf("#======================================#\n"); printf("| The tests consists in measuring the |\n"); printf("| time it takes to each generator to |\n"); printf("| generate 10 million random numbers |\n"); printf("| |\n"); printf("+--------------------------------------+\n"); printf("| 32 Bits |\n"); printf("+--------------------------------------+\n"); #if ISAAC_RAND || RANDS_USE_ALL isaac_srand(time(NULL)); for(j = 0; j < 10; j++) { clock_gettime(CLOCK_MONOTONIC,&tp1); for(i = 0; i < 10000000; i++) isaac_rand(); clock_gettime(CLOCK_MONOTONIC,&tp2); elapsed_time = (unsigned long) (tp2.tv_sec-tp1.tv_sec)*1000000000 + \ (unsigned long) tp2.tv_nsec-tp1.tv_nsec; times[j] = elapsed_time; } calc_mean_var(&mean,&var,times); printf("| ISAAC: %.4lf ± %.4lf |\n",mean/1e9, sqrt(var)/1e9); #endif #if ISAAC_X64_RAND || RANDS_USE_ALL isaac_srand(time(NULL)); for(j = 0; j < 10; j++) { clock_gettime(CLOCK_MONOTONIC,&tp1); for(i = 0; i < 5000000; i++) isaac_x64_rand(); clock_gettime(CLOCK_MONOTONIC,&tp2); elapsed_time = (unsigned long) (tp2.tv_sec-tp1.tv_sec)*1000000000 + \ (unsigned long) tp2.tv_nsec-tp1.tv_nsec; times[j] = elapsed_time; } calc_mean_var(&mean,&var,times); printf("| ISAAC (64bits): %.4lf ± %.4lf |\n",mean/1e9, sqrt(var)/1e9); #endif #if PR_RAND || RANDS_USE_ALL pr_srand(time(NULL)); for(j = 0; j < 10; j++) { clock_gettime(CLOCK_MONOTONIC,&tp1); for(i = 0; i < 10000000; i++) pr_rand(); clock_gettime(CLOCK_MONOTONIC,&tp2); elapsed_time = (unsigned long) (tp2.tv_sec-tp1.tv_sec)*1000000000 + \ (unsigned long) tp2.tv_nsec-tp1.tv_nsec; times[j] = elapsed_time; } calc_mean_var(&mean,&var,times); printf("| Parisi-Rapuano: %.4lf ± %.4lf |\n",mean/1e9, sqrt(var)/1e9); #endif #if __SSE2__ #if PR_SSE_RAND || RANDS_USE_ALL pr_sse_srand(time(NULL)); for(j = 0; j < 10; j++) { clock_gettime(CLOCK_MONOTONIC,&tp1); for(i = 0; i < 10000000; i++) pr_sse_rand(); clock_gettime(CLOCK_MONOTONIC,&tp2); elapsed_time = (unsigned long) (tp2.tv_sec-tp1.tv_sec)*1000000000 + \ (unsigned long) tp2.tv_nsec-tp1.tv_nsec; times[j] = elapsed_time; } calc_mean_var(&mean,&var,times); printf("| Parisi-Rapuano SSE: %.4lf ± %.4lf |\n",mean/1e9, sqrt(var)/1e9); #endif #endif srand(time(NULL)); for(j = 0; j < 10; j++) { clock_gettime(CLOCK_MONOTONIC,&tp1); for(i = 0; i < 10000000; i++) rand(); clock_gettime(CLOCK_MONOTONIC,&tp2); elapsed_time = (unsigned long) (tp2.tv_sec-tp1.tv_sec)*1000000000 + \ (unsigned long) tp2.tv_nsec-tp1.tv_nsec; times[j] = elapsed_time; } calc_mean_var(&mean,&var,times); printf("| Rand (stdlib): %.4lf ± %.4lf |\n",mean/1e9, sqrt(var)/1e9); #if MT_RAND || RANDS_USE_ALL mt_srand(time(NULL)); for(j = 0; j < 10; j++) { clock_gettime(CLOCK_MONOTONIC,&tp1); for(i = 0; i < 10000000; i++) mt_rand(); clock_gettime(CLOCK_MONOTONIC,&tp2); elapsed_time = (unsigned long) (tp2.tv_sec-tp1.tv_sec)*1000000000 + \ (unsigned long) tp2.tv_nsec-tp1.tv_nsec; times[j] = elapsed_time; } calc_mean_var(&mean,&var,times); printf("| Mersenne Twister: %.4lf ± %.4lf |\n",mean/1e9, sqrt(var)/1e9); #endif #if WELL_RAND || RANDS_USE_ALL well_srand(time(NULL)); for(j = 0; j < 10; j++) { clock_gettime(CLOCK_MONOTONIC,&tp1); for(i = 0; i < 10000000; i++) well_rand(); clock_gettime(CLOCK_MONOTONIC,&tp2); elapsed_time = (unsigned long) (tp2.tv_sec-tp1.tv_sec)*1000000000 + \ (unsigned long) tp2.tv_nsec-tp1.tv_nsec; times[j] = elapsed_time; } calc_mean_var(&mean,&var,times); printf("| WELL512: %.4lf ± %.4lf |\n",mean/1e9, sqrt(var)/1e9); #endif #if WELL_X64_RAND || RANDS_USE_ALL well_x64_srand(time(NULL)); for(j = 0; j < 10; j++) { clock_gettime(CLOCK_MONOTONIC,&tp1); for(i = 0; i < 5000000; i++) well_x64_rand(); clock_gettime(CLOCK_MONOTONIC,&tp2); elapsed_time = (unsigned long) (tp2.tv_sec-tp1.tv_sec)*1000000000 + \ (unsigned long) tp2.tv_nsec-tp1.tv_nsec; times[j] = elapsed_time; } calc_mean_var(&mean,&var,times); printf("| WELL512 (64bits): %.4lf ± %.4lf |\n",mean/1e9, sqrt(var)/1e9); #endif #if XOR_RAND || RANDS_USE_ALL xor_srand(time(NULL)); for(j = 0; j < 10; j++) { clock_gettime(CLOCK_MONOTONIC,&tp1); for(i = 0; i < 10000000; i++) xor_rand(); clock_gettime(CLOCK_MONOTONIC,&tp2); elapsed_time = (unsigned long) (tp2.tv_sec-tp1.tv_sec)*1000000000 + \ (unsigned long) tp2.tv_nsec-tp1.tv_nsec; times[j] = elapsed_time; } calc_mean_var(&mean,&var,times); printf("| Xorshift: %.4lf ± %.4lf |\n",mean/1e9, sqrt(var)/1e9); #endif // END OF 32 BITS printf("+--------------------------------------+\n"); printf("+--------------------------------------+\n"); printf("| 64 Bits |\n"); printf("+--------------------------------------+\n"); #if ISAAC_RAND || RANDS_USE_ALL isaac_srand(time(NULL)); for(j = 0; j < 10; j++) { clock_gettime(CLOCK_MONOTONIC,&tp1); for(i = 0; i < 20000000; i++) isaac_rand(); clock_gettime(CLOCK_MONOTONIC,&tp2); elapsed_time = (unsigned long) (tp2.tv_sec-tp1.tv_sec)*1000000000 + \ (unsigned long) tp2.tv_nsec-tp1.tv_nsec; times[j] = elapsed_time; } calc_mean_var(&mean,&var,times); printf("| ISAAC: %.4lf ± %.4lf |\n",mean/1e9, sqrt(var)/1e9); #endif #if ISAAC_X64_RAND || RANDS_USE_ALL isaac_srand(time(NULL)); for(j = 0; j < 10; j++) { clock_gettime(CLOCK_MONOTONIC,&tp1); for(i = 0; i < 10000000; i++) isaac_x64_rand(); clock_gettime(CLOCK_MONOTONIC,&tp2); elapsed_time = (unsigned long) (tp2.tv_sec-tp1.tv_sec)*1000000000 + \ (unsigned long) tp2.tv_nsec-tp1.tv_nsec; times[j] = elapsed_time; } calc_mean_var(&mean,&var,times); printf("| ISAAC (64bits): %.4lf ± %.4lf |\n",mean/1e9, sqrt(var)/1e9); #endif #if PR_RAND || RANDS_USE_ALL pr_srand(time(NULL)); for(j = 0; j < 10; j++) { clock_gettime(CLOCK_MONOTONIC,&tp1); for(i = 0; i < 20000000; i++) pr_rand(); clock_gettime(CLOCK_MONOTONIC,&tp2); elapsed_time = (unsigned long) (tp2.tv_sec-tp1.tv_sec)*1000000000 + \ (unsigned long) tp2.tv_nsec-tp1.tv_nsec; times[j] = elapsed_time; } calc_mean_var(&mean,&var,times); printf("| Parisi-Rapuano: %.4lf ± %.4lf |\n",mean/1e9, sqrt(var)/1e9); #endif #if __SSE2__ #if PR_SSE_RAND || RANDS_USE_ALL pr_sse_srand(time(NULL)); for(j = 0; j < 10; j++) { clock_gettime(CLOCK_MONOTONIC,&tp1); for(i = 0; i < 20000000; i++) pr_sse_rand(); clock_gettime(CLOCK_MONOTONIC,&tp2); elapsed_time = (unsigned long) (tp2.tv_sec-tp1.tv_sec)*1000000000 + \ (unsigned long) tp2.tv_nsec-tp1.tv_nsec; times[j] = elapsed_time; } calc_mean_var(&mean,&var,times); printf("| Parisi-Rapuano SSE: %.4lf ± %.4lf |\n",mean/1e9, sqrt(var)/1e9); #endif #endif srand(time(NULL)); for(j = 0; j < 10; j++) { clock_gettime(CLOCK_MONOTONIC,&tp1); for(i = 0; i < 20000000; i++) rand(); clock_gettime(CLOCK_MONOTONIC,&tp2); elapsed_time = (unsigned long) (tp2.tv_sec-tp1.tv_sec)*1000000000 + \ (unsigned long) tp2.tv_nsec-tp1.tv_nsec; times[j] = elapsed_time; } calc_mean_var(&mean,&var,times); printf("| Rand (stdlib): %.4lf ± %.4lf |\n",mean/1e9, sqrt(var)/1e9); #if MT_RAND || RANDS_USE_ALL mt_srand(time(NULL)); for(j = 0; j < 10; j++) { clock_gettime(CLOCK_MONOTONIC,&tp1); for(i = 0; i < 20000000; i++) mt_rand(); clock_gettime(CLOCK_MONOTONIC,&tp2); elapsed_time = (unsigned long) (tp2.tv_sec-tp1.tv_sec)*1000000000 + \ (unsigned long) tp2.tv_nsec-tp1.tv_nsec; times[j] = elapsed_time; } calc_mean_var(&mean,&var,times); printf("| Mersenne Twister: %.4lf ± %.4lf |\n",mean/1e9, sqrt(var)/1e9); #endif #if WELL_RAND || RANDS_USE_ALL well_srand(time(NULL)); for(j = 0; j < 10; j++) { clock_gettime(CLOCK_MONOTONIC,&tp1); for(i = 0; i < 20000000; i++) well_rand(); clock_gettime(CLOCK_MONOTONIC,&tp2); elapsed_time = (unsigned long) (tp2.tv_sec-tp1.tv_sec)*1000000000 + \ (unsigned long) tp2.tv_nsec-tp1.tv_nsec; times[j] = elapsed_time; } calc_mean_var(&mean,&var,times); printf("| WELL512: %.4lf ± %.4lf |\n",mean/1e9, sqrt(var)/1e9); #endif #if WELL_X64_RAND || RANDS_USE_ALL well_x64_srand(time(NULL)); for(j = 0; j < 10; j++) { clock_gettime(CLOCK_MONOTONIC,&tp1); for(i = 0; i < 10000000; i++) well_x64_rand(); clock_gettime(CLOCK_MONOTONIC,&tp2); elapsed_time = (unsigned long) (tp2.tv_sec-tp1.tv_sec)*1000000000 + \ (unsigned long) tp2.tv_nsec-tp1.tv_nsec; times[j] = elapsed_time; } calc_mean_var(&mean,&var,times); printf("| WELL512 (64bits): %.4lf ± %.4lf |\n",mean/1e9, sqrt(var)/1e9); #endif #if XOR_RAND || RANDS_USE_ALL xor_srand(time(NULL)); for(j = 0; j < 10; j++) { clock_gettime(CLOCK_MONOTONIC,&tp1); for(i = 0; i < 20000000; i++) xor_rand(); clock_gettime(CLOCK_MONOTONIC,&tp2); elapsed_time = (unsigned long) (tp2.tv_sec-tp1.tv_sec)*1000000000 + \ (unsigned long) tp2.tv_nsec-tp1.tv_nsec; times[j] = elapsed_time; } calc_mean_var(&mean,&var,times); printf("| Xorshift: %.4lf ± %.4lf |\n",mean/1e9, sqrt(var)/1e9); #endif // END OF 64 BITS printf("+--------------------------------------+\n"); return 0; }
uint32_t rng_gen_u32(rust_rng* rng) { uint32_t x = isaac_rand(&rng->rctx); rng_maybe_reseed(rng); return x; }