void save_minimum() { if (results->N == 0) { save_n(1); settime(0); } else { save_n(results->v[results->N - 1].n); settime(results->v[results->N - 1].u); } }
void save_minimum() { if (results.N == 0) { save_n(1); settime(0); } else { save_n(results.n[results.N - 1]); settime(results.u[results.N - 1]); } }
void save_median() { int i = results.N / 2; uint64 u, n; if (results.N == 0) { n = 1; u = 0; } else if (results.N % 2) { n = results.n[i]; u = results.u[i]; } else { n = (results.n[i] + results.n[i-1]) / 2; u = (results.u[i] + results.u[i-1]) / 2; } save_n(n); settime(u); }
void save_median() { int i = results->N / 2; uint64 u, n; if (results->N == 0) { n = 1; u = 0; } else if (results->N % 2) { n = results->v[i].n; u = results->v[i].u; } else { n = (results->v[i].n + results->v[i-1].n) / 2; u = (results->v[i].u + results->v[i-1].u) / 2; } #ifdef _DEBUG fprintf(stderr, "save_median: N=%d, n=%lu, u=%lu\n", results->N, (unsigned long)n, (unsigned long)u); #endif /* _DEBUG */ save_n(n); settime(u); }
void loads(size_t len, size_t range, size_t stride, int parallel, int warmup, int repetitions) { double result; size_t count; struct mem_state state; if (range < stride) return; state.width = 1; state.len = range; state.maxlen = len; state.line = stride; state.pagesize = getpagesize(); count = 100 * (state.len / (state.line * 100) + 1); #if 0 (*fpInit)(0, &state); fprintf(stderr, "loads: after init\n"); (*benchmark_loads)(2, &state); fprintf(stderr, "loads: after benchmark\n"); mem_cleanup(0, &state); fprintf(stderr, "loads: after cleanup\n"); settime(1); save_n(1); #else /* * Now walk them and time it. */ benchmp(fpInit, benchmark_loads, mem_cleanup, 100000, parallel, warmup, repetitions, &state); #endif /* We want to get to nanoseconds / load. */ save_minimum(); result = (1000. * (double)gettime()) / (double)(count * get_n()); fprintf(stderr, "%.5f %.3f\n", range / (1024. * 1024.), result); }
iter_t benchmp_interval(void* _state) { char c; iter_t iterations; double result; fd_set fds; struct timeval timeout; benchmp_child_state* state = (benchmp_child_state*)_state; iterations = (state->state == timing_interval ? state->iterations : state->iterations_batch); if (state->need_warmup) { /* remove spurious compilation warning */ result = state->enough; } else { result = stop(0,0); if (state->cleanup) { if (benchmp_sigchld_handler == SIG_DFL) signal(SIGCHLD, SIG_DFL); (*state->cleanup)(iterations, state->cookie); } save_n(state->iterations); result -= t_overhead() + get_n() * l_overhead(); settime(result >= 0. ? (uint64)result : 0.); } /* if the parent died, then give up */ if (getppid() == 1 && state->cleanup) { if (benchmp_sigchld_handler == SIG_DFL) signal(SIGCHLD, SIG_DFL); (*state->cleanup)(0, state->cookie); exit(0); } timeout.tv_sec = 0; timeout.tv_usec = 0; FD_ZERO(&fds); switch (state->state) { case warmup: iterations = state->iterations_batch; FD_SET(state->start_signal, &fds); select(state->start_signal+1, &fds, NULL, NULL, &timeout); if (FD_ISSET(state->start_signal, &fds)) { state->state = timing_interval; read(state->start_signal, &c, sizeof(char)); iterations = state->iterations; } if (state->need_warmup) { state->need_warmup = 0; /* send 'ready' */ write(state->response, &c, sizeof(char)); } break; case timing_interval: iterations = state->iterations; if (state->parallel > 1 || result > 0.95 * state->enough) { insertsort(gettime(), get_n(), get_results()); state->i++; /* we completed all the experiments, return results */ if (state->i >= state->repetitions) { state->state = cooldown; } } if (state->parallel == 1 && (result < 0.99 * state->enough || result > 1.2 * state->enough)) { if (result > 150.) { double tmp = iterations / result; tmp *= 1.1 * state->enough; iterations = (iter_t)(tmp + 1); } else { iterations <<= 3; if (iterations > 1<<27 || (result < 0. && iterations > 1<<20)) { state->state = cooldown; } } } state->iterations = iterations; if (state->state == cooldown) { /* send 'done' */ write(state->response, (void*)&c, sizeof(char)); iterations = state->iterations_batch; } break; case cooldown: iterations = state->iterations_batch; FD_SET(state->result_signal, &fds); select(state->result_signal+1, &fds, NULL, NULL, &timeout); if (FD_ISSET(state->result_signal, &fds)) { /* * At this point all children have stopped their * measurement loops, so we can block waiting for * the parent to tell us to send our results back. * From this point on, we will do no more "work". */ read(state->result_signal, (void*)&c, sizeof(char)); write(state->response, (void*)get_results(), state->r_size); if (state->cleanup) { if (benchmp_sigchld_handler == SIG_DFL) signal(SIGCHLD, SIG_DFL); (*state->cleanup)(0, state->cookie); } /* Now wait for signal to exit */ read(state->exit_signal, (void*)&c, sizeof(char)); exit(0); } }; if (state->initialize) { (*state->initialize)(iterations, state->cookie); } start(0); return (iterations); }
void benchmp(benchmp_f initialize, benchmp_f benchmark, benchmp_f cleanup, int enough, int parallel, int warmup, int repetitions, void* cookie) { iter_t iterations = 1; long i; pid_t *pids = NULL; int response[2]; int start_signal[2]; int result_signal[2]; int exit_signal[2]; #ifdef _DEBUG fprintf(stderr, "benchmp(%p, %p, %p, %d, %d, %d, %d, %p): entering\n", initialize, benchmark, cleanup, enough, parallel, warmup, repetitions, cookie); #endif enough = get_enough(enough); #ifdef _DEBUG fprintf(stderr, "\tenough=%d\n", enough); #endif if (repetitions < 0) repetitions = (1 < parallel || 1000000 <= enough ? 1 : TRIES); /* initialize results */ settime(0); save_n(1); if (parallel > 1) { /* Compute the baseline performance */ benchmp(initialize, benchmark, cleanup, enough, 1, warmup, repetitions, cookie); /* if we can't even do a single job, then give up */ if (gettime() == 0) return; /* calculate iterations for 1sec runtime */ iterations = get_n(); if (enough < SHORT) { double tmp = (double)SHORT * (double)get_n(); tmp /= (double)gettime(); iterations = (iter_t)tmp + 1; } settime(0); save_n(1); } /* Create the necessary pipes for control */ if (pipe(response) < 0 || pipe(start_signal) < 0 || pipe(result_signal) < 0 || pipe(exit_signal) < 0) { #ifdef _DEBUG fprintf(stderr, "BENCHMP: Could not create control pipes\n"); #endif /* _DEBUG */ return; } /* fork the necessary children */ benchmp_sigchld_received = 0; benchmp_sigterm_received = 0; benchmp_sigterm_handler = signal(SIGTERM, benchmp_sigterm); benchmp_sigchld_handler = signal(SIGCHLD, benchmp_sigchld); pids = (pid_t*)malloc(parallel * sizeof(pid_t)); if (!pids) return; bzero((void*)pids, parallel * sizeof(pid_t)); for (i = 0; i < parallel; ++i) { if (benchmp_sigterm_received) goto error_exit; #ifdef _DEBUG fprintf(stderr, "benchmp(%p, %p, %p, %d, %d, %d, %d, %p): creating child %d\n", initialize, benchmark, cleanup, enough, parallel, warmup, repetitions, cookie, i); #endif switch(pids[i] = fork()) { case -1: /* could not open enough children! */ #ifdef _DEBUG fprintf(stderr, "BENCHMP: fork() failed!\n"); #endif /* _DEBUG */ goto error_exit; case 0: /* If child */ close(response[0]); close(start_signal[1]); close(result_signal[1]); close(exit_signal[1]); handle_scheduler(i, 0, 0); benchmp_child(initialize, benchmark, cleanup, i, response[1], start_signal[0], result_signal[0], exit_signal[0], enough, iterations, parallel, repetitions, cookie ); exit(0); default: break; } } close(response[1]); close(start_signal[0]); close(result_signal[0]); close(exit_signal[0]); benchmp_parent(response[0], start_signal[1], result_signal[1], exit_signal[1], pids, parallel, iterations, warmup, repetitions, enough ); goto cleanup_exit; error_exit: /* give the children a chance to clean up gracefully */ signal(SIGCHLD, SIG_DFL); while (--i >= 0) { kill(pids[i], SIGTERM); waitpid(pids[i], NULL, 0); } cleanup_exit: /* * Clean up and kill all children * * NOTE: the children themselves SHOULD exit, and * Killing them could prevent them from * cleanup up subprocesses, etc... So, we only * want to kill child processes when it appears * that they will not die of their own accord. * We wait twice the timing interval plus two seconds * for children to die. If they haven't died by * that time, then we start killing them. */ benchmp_sigalrm_timeout = (int)((2 * enough)/1000000) + 2; if (benchmp_sigalrm_timeout < 5) benchmp_sigalrm_timeout = 5; signal(SIGCHLD, SIG_DFL); while (i-- > 0) { /* wait timeout seconds for child to die, then kill it */ benchmp_sigalrm_pid = pids[i]; benchmp_sigalrm_handler = signal(SIGALRM, benchmp_sigalrm); alarm(benchmp_sigalrm_timeout); waitpid(pids[i], NULL, 0); alarm(0); signal(SIGALRM, benchmp_sigalrm_handler); } if (pids) free(pids); #ifdef _DEBUG fprintf(stderr, "benchmp(0x%x, 0x%x, 0x%x, %d, %d, 0x%x): exiting\n", (unsigned int)initialize, (unsigned int)benchmark, (unsigned int)cleanup, enough, parallel, (unsigned int)cookie); #endif }