Browse Source

Windows' timer resolution is limited to 15ms accuracy. This was breaking dynamic intensity since it tries to measure below this.

Since we are repeatedly sampling similar timeframes, we can average the gpu_us result over 5 different values to get very fine precision.
nfactor-troky
Con Kolivas 12 years ago
parent
commit
8745ba1e6d
  1. 26
      driver-opencl.c
  2. 6
      miner.h
  3. 6
      util.c

26
driver-opencl.c

@ -1490,6 +1490,7 @@ static int64_t opencl_scanhash(struct thr_info *thr, struct work *work, @@ -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, @@ -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, @@ -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, @@ -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];

6
miner.h

@ -366,9 +366,10 @@ struct cgpu_info { @@ -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 @@ -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;

6
util.c

@ -705,3 +705,9 @@ void nmsleep(unsigned int msecs) @@ -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;
}

Loading…
Cancel
Save