[time-nuts] Divide by five ->Ensemble

Paul tic-toc at bodosom.net
Sun Nov 9 19:39:06 EST 2014

On Sun, Nov 9, 2014 at 6:18 PM, Bob Camp <kb8tq at n1k.org> wrote:

> The NTP algorithm as it is written and as it is implemented results in an
> output clock that does *not* improve when a number of very good clocks are
> being used and the output is compared to the input. In that case and that
> case alone, the system simply does what one of the clocks is doing. That's
> the case that matters when you are looking at a bunch of similar Rb's.

I would naively compare input to output like this using ntpq (values in ms)
 On a local S2 server, (estimated) system clock offset from UTC:
 Average offset from the "system peer" (which does happen to have the
smallest offset among all servers): offset=-0.019

The best view would likely come from turning on debugging.  Viz the DPRINTF
below from ntp_proto in the 476 dev release:
         * Mitigation rules of the game. We have the pick of the
         * litter in typesystem if any survivors are left. If
         * there is a prefer peer, use its offset and jitter.
         * Otherwise, use the combined offset and jitter of all kitters.
        if (typesystem != NULL) {
                if (sys_prefer == NULL) {
                        typesystem->new_status = CTL_PST_SEL_SYSPEER;
                        clock_combine(peers, sys_survivors, speer);
                } else {
                        typesystem = sys_prefer;
                        sys_clockhop = 0;
                        typesystem->new_status = CTL_PST_SEL_SYSPEER;
                        sys_offset = typesystem->offset;
                        sys_jitter = typesystem->jitter;
                DPRINTF(1, ("select: combine offset %.9f jitter %.9f\n",
                        sys_offset, sys_jitter));

and clock_combine while simple is not empty:

        peer_select *   peers,  /* survivor list */
        int             npeers, /* number of survivors */
        int             syspeer /* index of sys.peer */
        int     i;
        double  x, y, z, w;

        y = z = w = 0;
        for (i = 0; i < npeers; i++) {
                x = 1. / peers[i].synch;
                y += x;
                z += x * peers[i].peer->offset;
                w += x * DIFF(peers[i].peer->offset,
        sys_offset = z / y;
        sys_jitter = SQRT(w / y + SQUARE(peers[syspeer].seljit));

As I said before I'm certainly not arguing that the  technique in
clock_combine() has any specific fitness or suitability for any purpose but
it certainly looks like it does what's documented modulo "prefer".

More information about the time-nuts mailing list