gmx_bool wallcycle_have_counter(void) { return gmx_cycles_have_counter(); }
/*! \brief Calculate number of seconds per cycle tick on host * * This routine runs a timer loop to calibrate the number of * seconds per the units returned fro gmx_cycles_read(). * * \param sampletime Minimum real sample time. It takes some trial-and-error * to find the correct delay loop size, so the total runtime of * this routine is about twice this time. * \return Number of seconds per cycle unit. If it is not possible to * calculate on this system (for whatever reason) the return value * will be -1, so check that it is positive before using it. */ double gmx_cycles_calibrate(double sampletime) { #ifdef _MSC_VER /* Windows does not have gettimeofday, but it provides a special * routine that returns the cycle counter frequency. */ LARGE_INTEGER i; QueryPerformanceFrequency(&i); return 1.0/static_cast<double>(i.QuadPart); /* end of MS Windows implementation */ #elif HAVE_GETTIMEOFDAY /* generic implementation with gettimeofday() */ struct timeval t1, t2; gmx_cycles_t c1, c2; double timediff, cyclediff; double d = 0.1; /* Dummy variable so we don't optimize away delay loop */ if (!gmx_cycles_have_counter()) { return -1; } #if (defined(__alpha__) || defined(__alpha)) /* Alpha cannot count to more than 4e9, but I don't expect * that the architecture will go over 2GHz before it dies, so * up to 2.0 seconds of sampling should be safe. */ if (sampletime > 2.0) { sampletime = 2.0; } #endif /* Start a timing loop. We want this to be largely independent * of machine speed, so we need to start with a very small number * of iterations and repeat it until we reach the requested time. * * We call gettimeofday an extra time at the start to avoid cache misses. */ gettimeofday(&t1, nullptr); gettimeofday(&t1, nullptr); c1 = gmx_cycles_read(); do { /* just a delay loop. To avoid optimizing it away, we calculate a number * that will underflow to zero in most cases. By conditionally adding it * to a result at the end it cannot be removed. n=10000 is arbitrary... */ for (int i = 0; i < 10000; i++) { d = d/(1.0+static_cast<double>(i)); } /* Read the time again */ gettimeofday(&t2, nullptr); c2 = gmx_cycles_read(); timediff = static_cast<double>(t2.tv_sec-t1.tv_sec)+(t2.tv_usec-t1.tv_usec)*1e-6; } while (timediff < sampletime); cyclediff = c2-c1; /* Add a very small result so the delay loop cannot be optimized away */ if (d < 1e-30) { timediff += d; } /* Return seconds per cycle */ return timediff/cyclediff; #else /* No timing function available */ return -1; #endif }