diff --git a/driver-opencl.c b/driver-opencl.c index b6dfe12e..78908bff 100644 --- a/driver-opencl.c +++ b/driver-opencl.c @@ -1490,6 +1490,7 @@ static int64_t opencl_scanhash(struct thr_info *thr, struct work *work, _clState *clState = clStates[thr_id]; const cl_kernel *kernel = &clState->kernel; const int dynamic_us = opt_dynamic_interval * 1000; + struct timeval tv_gpuend; cl_bool blocking; cl_int status; @@ -1508,13 +1509,17 @@ static int64_t opencl_scanhash(struct thr_info *thr, struct work *work, clFinish(clState->commandQueue); if (gpu->dynamic) { - struct timeval diff; - suseconds_t gpu_us; - - gettimeofday(&gpu->tv_gpuend, NULL); - timersub(&gpu->tv_gpuend, &gpu->tv_gpustart, &diff); - gpu_us = diff.tv_sec * 1000000 + diff.tv_usec; - if (likely(gpu_us >= 0)) { + double gpu_us; + + /* Windows returns the same time for gettimeofday due to its + * 15ms timer resolution, so we must average the result over + * at least 5 values that are actually different to get an + * accurate result */ + gpu->intervals++; + gettimeofday(&tv_gpuend, NULL); + gpu_us = us_tdiff(&tv_gpuend, &gpu->tv_gpumid); + if (gpu_us > 0 && ++gpu->hit > 4) { + gpu_us = us_tdiff(&tv_gpuend, &gpu->tv_gpustart) / gpu->intervals; gpu->gpu_us_average = (gpu->gpu_us_average + gpu_us * 0.63) / 1.63; /* Try to not let the GPU be out for longer than @@ -1527,6 +1532,7 @@ static int64_t opencl_scanhash(struct thr_info *thr, struct work *work, if (gpu->intensity < MAX_INTENSITY) ++gpu->intensity; } + gpu->intervals = gpu->hit = 0; } } set_threads_hashes(clState->vwidth, &threads, &hashes, globalThreads, @@ -1562,7 +1568,11 @@ static int64_t opencl_scanhash(struct thr_info *thr, struct work *work, clFinish(clState->commandQueue); } - gettimeofday(&gpu->tv_gpustart, NULL); + gettimeofday(&gpu->tv_gpumid, NULL); + if (!gpu->intervals) { + gpu->tv_gpustart.tv_sec = gpu->tv_gpumid.tv_sec; + gpu->tv_gpustart.tv_usec = gpu->tv_gpumid.tv_usec; + } if (clState->goffset) { size_t global_work_offset[1]; diff --git a/miner.h b/miner.h index af66e85f..26d628bb 100644 --- a/miner.h +++ b/miner.h @@ -366,9 +366,10 @@ struct cgpu_info { int opt_tc, thread_concurrency; int shaders; #endif - struct timeval tv_gpustart;; - struct timeval tv_gpuend; + struct timeval tv_gpustart; + struct timeval tv_gpumid; double gpu_us_average; + int intervals, hit; #endif float temp; @@ -440,6 +441,7 @@ extern int thr_info_create(struct thr_info *thr, pthread_attr_t *attr, void *(*s extern void thr_info_cancel(struct thr_info *thr); extern void thr_info_freeze(struct thr_info *thr); extern void nmsleep(unsigned int msecs); +extern double us_tdiff(struct timeval *end, struct timeval *start); struct string_elist { char *string; diff --git a/util.c b/util.c index 822e61df..b104d8a3 100644 --- a/util.c +++ b/util.c @@ -705,3 +705,9 @@ void nmsleep(unsigned int msecs) ret = nanosleep(&twait, &tleft); } while (ret == -1 && errno == EINTR); } + +/* Returns the microseconds difference between end and start times as a double */ +double us_tdiff(struct timeval *end, struct timeval *start) +{ + return end->tv_sec * 1000000 + end->tv_usec - start->tv_sec * 1000000 - start->tv_usec; +}