示例#1
0
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);
	}
}
示例#2
0
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]);
    }
}
示例#3
0
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);
}
示例#4
0
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);
}
示例#5
0
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);

}
示例#6
0
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);
}
示例#7
0
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
}