Skip to content

Commit

Permalink
opencl: Nearly complete migration to per-work mining algorithms
Browse files Browse the repository at this point in the history
  • Loading branch information
luke-jr committed Nov 5, 2014
1 parent ad3c4c8 commit fbfab8b
Show file tree
Hide file tree
Showing 8 changed files with 161 additions and 71 deletions.
6 changes: 5 additions & 1 deletion api.c
Original file line number Diff line number Diff line change
Expand Up @@ -2683,7 +2683,11 @@ static void gpuintensity(struct io_data *io_data, __maybe_unused SOCKETTYPE c, c
if (data->dynamic)
strcpy(intensitystr, DYNAMIC);
else
snprintf(intensitystr, sizeof(intensitystr), "%g", oclthreads_to_intensity(data->oclthreads, !opt_scrypt));
{
const char *iunit;
float intensity = opencl_proc_get_intensity(cgpu, &iunit);
snprintf(intensitystr, sizeof(intensitystr), "%s%g", iunit, intensity);
}
}
else
{
Expand Down
122 changes: 75 additions & 47 deletions driver-opencl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand All @@ -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);
}
Expand Down Expand Up @@ -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";
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
}
Expand Down
17 changes: 1 addition & 16 deletions driver-opencl.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,6 @@

#include "miner.h"

#define MIN_SHA_INTENSITY -10
#define MAX_SHA_INTENSITY 14
#define MIN_SCRYPT_INTENSITY 8
#define MAX_SCRYPT_INTENSITY 31
#ifdef USE_SCRYPT
#define MIN_INTENSITY (opt_scrypt ? MIN_SCRYPT_INTENSITY : MIN_SHA_INTENSITY)
#define MAX_INTENSITY (opt_scrypt ? MAX_SCRYPT_INTENSITY : MAX_SHA_INTENSITY)
#define MAX_GPU_INTENSITY MAX_SCRYPT_INTENSITY
#else
#define MIN_INTENSITY MIN_SHA_INTENSITY
#define MAX_INTENSITY MAX_SHA_INTENSITY
#define MAX_GPU_INTENSITY MAX_SHA_INTENSITY
#endif

enum opencl_binary_usage {
OBU_DEFAULT = 0,
OBU_LOAD = 1,
Expand Down Expand Up @@ -78,8 +64,7 @@ struct opencl_device_data {
#endif
};

extern double oclthreads_to_intensity(unsigned long oclthreads, bool is_sha256d);
extern unsigned long intensity_to_oclthreads(double intensity, bool is_sha256d);
extern float opencl_proc_get_intensity(struct cgpu_info *, const char **iunit);
extern unsigned long xintensity_to_oclthreads(double xintensity, cl_uint max_compute_units);
extern bool opencl_set_intensity_from_str(struct cgpu_info *, const char *newvalue);

Expand Down
15 changes: 12 additions & 3 deletions findnonce.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ void precalc_hash(struct opencl_work_data *blk, uint32_t *state, uint32_t *data)
struct pc_data {
struct thr_info *thr;
struct work work;
uint32_t res[SCRYPT_MAXBUFFERS];
uint32_t res[OPENCL_MAX_BUFFERSIZE];
pthread_t pth;
int found;
};
Expand All @@ -147,7 +147,11 @@ static void *postcalc_hash(void *userdata)
struct pc_data *pcd = (struct pc_data *)userdata;
struct thr_info *thr = pcd->thr;
unsigned int entry = 0;
int found = (work_mining_algorithm(&pcd->work)->algo == POW_SCRYPT) ? SCRYPT_FOUND : FOUND;
int found = FOUND;
#ifdef USE_SCRYPT
if (work_mining_algorithm(&pcd->work)->algo == POW_SCRYPT)
found = SCRYPT_FOUND;
#endif

pthread_detach(pthread_self());
RenameThread("postcalchsh");
Expand Down Expand Up @@ -188,7 +192,12 @@ void postcalc_hash_async(struct thr_info *thr, struct work *work, uint32_t *res)
.thr = thr,
};
__copy_work(&pcd->work, work);
buffersize = (work_mining_algorithm(work)->algo == POW_SCRYPT) ? SCRYPT_BUFFERSIZE : BUFFERSIZE;
#ifdef USE_SCRYPT
if (work_mining_algorithm(work)->algo == POW_SCRYPT)
buffersize = SCRYPT_BUFFERSIZE;
else
#endif
buffersize = BUFFERSIZE;
memcpy(&pcd->res, res, buffersize);

if (pthread_create(&pcd->pth, NULL, postcalc_hash, (void *)pcd)) {
Expand Down
6 changes: 6 additions & 0 deletions findnonce.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,16 @@
#define BUFFERSIZE (sizeof(uint32_t) * MAXBUFFERS)
#define FOUND (0x0F)

#ifdef USE_SCRYPT
#define SCRYPT_MAXBUFFERS (0x100)
#define SCRYPT_BUFFERSIZE (sizeof(uint32_t) * SCRYPT_MAXBUFFERS)
#define SCRYPT_FOUND (0xFF)

#define OPENCL_MAX_BUFFERSIZE SCRYPT_BUFFERSIZE
#else
#define OPENCL_MAX_BUFFERSIZE BUFFERSIZE
#endif

#ifdef HAVE_OPENCL
extern void precalc_hash(struct opencl_work_data *blk, uint32_t *state, uint32_t *data);
extern void postcalc_hash_async(struct thr_info *thr, struct work *work, uint32_t *res);
Expand Down

0 comments on commit fbfab8b

Please sign in to comment.