|
|
@@ -663,22 +663,6 @@ _SET_INT_LIST(temp_overheat, (v >= 0 && v < 200), adl.overtemp )
|
|
|
#endif
|
|
|
|
|
|
#ifdef HAVE_OPENCL
|
|
|
-// SHA256d "intensity" has an artificial offset of -15
|
|
|
-double oclthreads_to_intensity(const unsigned long oclthreads, const bool is_sha256d)
|
|
|
-{
|
|
|
- double intensity = log2(oclthreads);
|
|
|
- if (is_sha256d)
|
|
|
- intensity -= 15.;
|
|
|
- return intensity;
|
|
|
-}
|
|
|
-
|
|
|
-unsigned long intensity_to_oclthreads(double intensity, const bool is_sha256d)
|
|
|
-{
|
|
|
- if (is_sha256d)
|
|
|
- intensity += 15;
|
|
|
- return pow(2, intensity);
|
|
|
-}
|
|
|
-
|
|
|
double oclthreads_to_xintensity(const unsigned long oclthreads, const cl_uint max_compute_units)
|
|
|
{
|
|
|
return (double)oclthreads / (double)max_compute_units / 64.;
|
|
|
@@ -689,6 +673,28 @@ unsigned long xintensity_to_oclthreads(const double xintensity, const cl_uint ma
|
|
|
return xintensity * max_compute_units * 0x40;
|
|
|
}
|
|
|
|
|
|
+static int min_intensity, max_intensity;
|
|
|
+
|
|
|
+// NOTE: This can't be attribute-constructor because then it would race with the mining_algorithms list being populated
|
|
|
+static
|
|
|
+void opencl_calc_intensity_range()
|
|
|
+{
|
|
|
+ RUNONCE();
|
|
|
+
|
|
|
+ min_intensity = INT_MAX;
|
|
|
+ max_intensity = INT_MIN;
|
|
|
+ struct mining_algorithm *malgo;
|
|
|
+ LL_FOREACH(mining_algorithms, malgo)
|
|
|
+ {
|
|
|
+ const int malgo_min_intensity = malgo->opencl_oclthreads_to_intensity(malgo->opencl_min_oclthreads);
|
|
|
+ const int malgo_max_intensity = malgo->opencl_oclthreads_to_intensity(malgo->opencl_max_oclthreads);
|
|
|
+ if (malgo_min_intensity < min_intensity)
|
|
|
+ min_intensity = malgo_min_intensity;
|
|
|
+ if (malgo_max_intensity > max_intensity)
|
|
|
+ max_intensity = malgo_max_intensity;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
bool opencl_set_intensity_from_str(struct cgpu_info * const cgpu, const char *_val)
|
|
|
{
|
|
|
struct opencl_device_data * const data = cgpu->device_data;
|
|
|
@@ -722,9 +728,10 @@ bool opencl_set_intensity_from_str(struct cgpu_info * const cgpu, const char *_v
|
|
|
if (isdigit(_val[0]))
|
|
|
{
|
|
|
const double v = atof(_val);
|
|
|
- if (v < MIN_INTENSITY || v > MAX_GPU_INTENSITY)
|
|
|
+ opencl_calc_intensity_range();
|
|
|
+ if (v < min_intensity || v > max_intensity)
|
|
|
return false;
|
|
|
- oclthreads = intensity_to_oclthreads(v, !opt_scrypt);
|
|
|
+ oclthreads = 1;
|
|
|
intensity = v;
|
|
|
}
|
|
|
|
|
|
@@ -815,14 +822,29 @@ struct device_drv opencl_api;
|
|
|
|
|
|
#endif /* HAVE_OPENCL */
|
|
|
|
|
|
+float opencl_proc_get_intensity(struct cgpu_info * const proc, const char ** const iunit)
|
|
|
+{
|
|
|
+ struct opencl_device_data * const data = proc->device_data;
|
|
|
+ struct thr_info *thr = proc->thr[0];
|
|
|
+ const int thr_id = thr->id;
|
|
|
+ _clState * const clState = clStates[thr_id];
|
|
|
+ float intensity = data->intensity;
|
|
|
+ if (intensity == intensity_not_set)
|
|
|
+ {
|
|
|
+ intensity = oclthreads_to_xintensity(data->oclthreads, clState->max_compute_units);
|
|
|
+ *iunit = data->dynamic ? "dx" : "x";
|
|
|
+ }
|
|
|
+ else
|
|
|
+ *iunit = data->dynamic ? "d" : "";
|
|
|
+ return intensity;
|
|
|
+}
|
|
|
+
|
|
|
#if defined(HAVE_OPENCL) && defined(HAVE_CURSES)
|
|
|
static
|
|
|
void opencl_wlogprint_status(struct cgpu_info *cgpu)
|
|
|
{
|
|
|
struct opencl_device_data * const data = cgpu->device_data;
|
|
|
struct thr_info *thr = cgpu->thr[0];
|
|
|
- const int thr_id = thr->id;
|
|
|
- _clState * const clState = clStates[thr_id];
|
|
|
int i;
|
|
|
char checkin[40];
|
|
|
double displayed_rolling;
|
|
|
@@ -831,16 +853,9 @@ void opencl_wlogprint_status(struct cgpu_info *cgpu)
|
|
|
strcpy(logline, ""); // In case it has no data
|
|
|
|
|
|
{
|
|
|
- double intensity = oclthreads_to_intensity(data->oclthreads, !opt_scrypt);
|
|
|
- double xintensity = oclthreads_to_xintensity(data->oclthreads, clState->max_compute_units);
|
|
|
- const char *iunit = "";
|
|
|
- if (xintensity - (int)xintensity < intensity - (int)intensity)
|
|
|
- {
|
|
|
- intensity = xintensity;
|
|
|
- iunit = "x";
|
|
|
- }
|
|
|
- tailsprintf(logline, sizeof(logline), "I:%s%s%g ",
|
|
|
- (data->dynamic ? "d" : ""),
|
|
|
+ const char *iunit;
|
|
|
+ float intensity = opencl_proc_get_intensity(cgpu, &iunit);
|
|
|
+ tailsprintf(logline, sizeof(logline), "I:%s%g ",
|
|
|
iunit,
|
|
|
intensity);
|
|
|
}
|
|
|
@@ -937,7 +952,8 @@ const char *opencl_tui_handle_choice(struct cgpu_info *cgpu, int input)
|
|
|
char promptbuf[0x40];
|
|
|
char *intvar;
|
|
|
|
|
|
- snprintf(promptbuf, sizeof(promptbuf), "Set GPU scan intensity (d or %d -> %d)", MIN_INTENSITY, MAX_INTENSITY);
|
|
|
+ opencl_calc_intensity_range();
|
|
|
+ snprintf(promptbuf, sizeof(promptbuf), "Set GPU scan intensity (d or %d -> %d)", min_intensity, max_intensity);
|
|
|
intvar = curses_input(promptbuf);
|
|
|
if (!intvar)
|
|
|
return "Invalid intensity\n";
|
|
|
@@ -1394,13 +1410,9 @@ static int opencl_autodetect()
|
|
|
if (!nDevs)
|
|
|
return 0;
|
|
|
|
|
|
- /* If opt_g_threads is not set, use default 1 thread on scrypt and
|
|
|
- * 2 for regular mining */
|
|
|
if (opt_g_threads == -1) {
|
|
|
- if (opt_scrypt)
|
|
|
- opt_g_threads = 1;
|
|
|
- else
|
|
|
- opt_g_threads = 2;
|
|
|
+ // NOTE: This should ideally default to 2 for non-scrypt
|
|
|
+ opt_g_threads = 1;
|
|
|
}
|
|
|
|
|
|
#ifdef HAVE_SENSORS
|
|
|
@@ -1446,9 +1458,13 @@ static int opencl_autodetect()
|
|
|
|
|
|
static void opencl_detect()
|
|
|
{
|
|
|
- int flags = 0;
|
|
|
- if (!opt_scrypt)
|
|
|
- flags |= GDF_DEFAULT_NOAUTO;
|
|
|
+ int flags = GDF_DEFAULT_NOAUTO;
|
|
|
+ struct mining_goal_info *goal, *tmpgoal;
|
|
|
+ HASH_ITER(hh, mining_goals, goal, tmpgoal)
|
|
|
+ {
|
|
|
+ if (!goal->malgo->opencl_nodefault)
|
|
|
+ flags &= ~GDF_DEFAULT_NOAUTO;
|
|
|
+ }
|
|
|
generic_detect(&opencl_api, NULL, opencl_autodetect, flags);
|
|
|
}
|
|
|
|
|
|
@@ -1547,8 +1563,18 @@ get_opencl_api_extra_device_status(struct cgpu_info *gpu)
|
|
|
root = api_add_int(root, "Powertune", &pt, true);
|
|
|
|
|
|
char intensity[20];
|
|
|
- uint32_t oclthreads = data->oclthreads;
|
|
|
- double intensityf = oclthreads_to_intensity(oclthreads, !opt_scrypt);
|
|
|
+ uint32_t oclthreads;
|
|
|
+ double intensityf = data->intensity;
|
|
|
+ // FIXME: Some way to express intensities malgo-neutral?
|
|
|
+ struct mining_goal_info * const goal = get_mining_goal("default");
|
|
|
+ struct mining_algorithm * const malgo = goal->malgo;
|
|
|
+ if (data->intensity == intensity_not_set)
|
|
|
+ {
|
|
|
+ oclthreads = data->oclthreads;
|
|
|
+ intensityf = malgo->opencl_oclthreads_to_intensity(oclthreads);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ oclthreads = malgo->opencl_intensity_to_oclthreads(intensityf);
|
|
|
double xintensity = oclthreads_to_xintensity(oclthreads, clState->max_compute_units);
|
|
|
if (data->dynamic)
|
|
|
strcpy(intensity, "D");
|
|
|
@@ -1577,7 +1603,7 @@ static bool opencl_thread_prepare(struct thr_info *thr)
|
|
|
int virtual_gpu = data->virtual_gpu;
|
|
|
int i = thr->id;
|
|
|
static bool failmessage = false;
|
|
|
- int buffersize = SCRYPT_BUFFERSIZE;
|
|
|
+ int buffersize = OPENCL_MAX_BUFFERSIZE;
|
|
|
|
|
|
if (!blank_res)
|
|
|
blank_res = calloc(buffersize, 1);
|
|
|
@@ -1634,7 +1660,7 @@ static bool opencl_thread_init(struct thr_info *thr)
|
|
|
cl_int status = 0;
|
|
|
thrdata = calloc(1, sizeof(*thrdata));
|
|
|
thr->cgpu_data = thrdata;
|
|
|
- int buffersize = SCRYPT_BUFFERSIZE;
|
|
|
+ int buffersize = OPENCL_MAX_BUFFERSIZE;
|
|
|
|
|
|
if (!thrdata) {
|
|
|
applog(LOG_ERR, "Failed to calloc in opencl_thread_init");
|
|
|
@@ -1787,6 +1813,8 @@ static int64_t opencl_scanhash(struct thr_info *thr, struct work *work,
|
|
|
buffersize = SCRYPT_BUFFERSIZE;
|
|
|
}
|
|
|
#endif
|
|
|
+ if (data->intensity != intensity_not_set)
|
|
|
+ data->oclthreads = malgo->opencl_intensity_to_oclthreads(data->intensity);
|
|
|
|
|
|
/* Windows' timer resolution is only 15ms so oversample 5x */
|
|
|
if (data->dynamic && (++data->intervals * dynamic_us) > 70000) {
|
|
|
@@ -1796,18 +1824,18 @@ static int64_t opencl_scanhash(struct thr_info *thr, struct work *work,
|
|
|
cgtime(&tv_gpuend);
|
|
|
gpu_us = us_tdiff(&tv_gpuend, &data->tv_gpustart) / data->intervals;
|
|
|
if (gpu_us > dynamic_us) {
|
|
|
- const unsigned long min_oclthreads = intensity_to_oclthreads(MIN_INTENSITY, !opt_scrypt);
|
|
|
+ const unsigned long min_oclthreads = malgo->opencl_min_oclthreads;
|
|
|
data->oclthreads /= 2;
|
|
|
if (data->oclthreads < min_oclthreads)
|
|
|
data->oclthreads = min_oclthreads;
|
|
|
} else if (gpu_us < dynamic_us / 2) {
|
|
|
- const unsigned long max_oclthreads = intensity_to_oclthreads(MAX_INTENSITY, !opt_scrypt);
|
|
|
+ const unsigned long max_oclthreads = malgo->opencl_max_oclthreads;
|
|
|
data->oclthreads *= 2;
|
|
|
if (data->oclthreads > max_oclthreads)
|
|
|
data->oclthreads = max_oclthreads;
|
|
|
}
|
|
|
if (data->intensity != intensity_not_set)
|
|
|
- data->intensity = oclthreads_to_intensity(data->oclthreads, !opt_scrypt);
|
|
|
+ data->intensity = malgo->opencl_oclthreads_to_intensity(data->oclthreads);
|
|
|
memcpy(&(data->tv_gpustart), &tv_gpuend, sizeof(struct timeval));
|
|
|
data->intervals = 0;
|
|
|
}
|