Browse Source

opencl: Accept arbitrary kernel filenames, provided they specify a kernel interface somewhere in the source file

File must include the string "kernel-interface:" followed by one of the known interface names
Luke Dashjr 11 years ago
parent
commit
4ab27d7b0e
10 changed files with 122 additions and 85 deletions
  1. 7 2
      README.GPU
  2. 0 6
      configure.ac
  3. 2 0
      diablo130302.cl
  4. 2 0
      diakgcn121016.cl
  5. 53 30
      driver-opencl.c
  6. 4 1
      driver-opencl.h
  7. 48 46
      ocl.c
  8. 2 0
      phatk121016.cl
  9. 2 0
      poclbm130302.cl
  10. 2 0
      scrypt130511.cl

+ 7 - 2
README.GPU

@@ -435,8 +435,13 @@ A: Your parameters are too high. Don't add GPU threads, don't set intensity too
 high, decrease thread concurrency. See the README.scrypt for a lot more help.
 
 Q: Are OpenCL kernels from other mining software useable in BFGMiner?
-A: No, the APIs are often slightly different between the different software and
-they will not work without modifying BFGMiner itself.
+A: The interfaces are often slightly different between the different software,
+so in most cases they will not work without modifying BFGMiner itself. However,
+if the kernel is compatible with one BFGMiner supports, you can edit it in a
+text editor and add a line that looks like this to the top:
+    // kernel-interface: poclbm
+This will instruct BFGMiner to use the poclbm kernel interface. Then to use the
+kernel, just use --set OCL:kernel=mykernel where the filename is mykernel.cl.
 
 Q: BFGMiner stops mining (or my GPUs go DEAD) and I can't close it?
 A: Once the driver has crashed, there is no way for BFGMiner to close cleanly.

+ 0 - 6
configure.ac

@@ -1646,12 +1646,6 @@ fi
 
 AM_CONDITIONAL([NEED_BITSTREAM_FPGAMINER], [test x$modminer$x6500 != xnono])
 
-AC_DEFINE_UNQUOTED([PHATK_KERNNAME], ["phatk121016"], [Filename for phatk kernel])
-AC_DEFINE_UNQUOTED([POCLBM_KERNNAME], ["poclbm130302"], [Filename for poclbm kernel])
-AC_DEFINE_UNQUOTED([DIAKGCN_KERNNAME], ["diakgcn121016"], [Filename for diakgcn kernel])
-AC_DEFINE_UNQUOTED([DIABLO_KERNNAME], ["diablo130302"], [Filename for diablo kernel])
-AC_DEFINE_UNQUOTED([SCRYPT_KERNNAME], ["scrypt130511"], [Filename for scrypt kernel])
-
 
 m4_define([BFG_PRINT_LIST],[
 	eval _mylist="\$$2"

+ 2 - 0
diablo130302.cl

@@ -17,6 +17,8 @@
  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+// kernel-interface: diablo
+
 #ifdef VECTORS4
 	typedef uint4 z;
 #elif defined(VECTORS2)

+ 2 - 0
diakgcn121016.cl

@@ -3,6 +3,8 @@
 // Parts and / or ideas for this kernel are based upon the public-domain poclbm project, the phatk kernel by Phateus and the DiabloMiner kernel by DiabloD3.
 // The kernel was rewritten by me (Diapolo) and is still public-domain!
 
+// kernel-interface: diakgcn
+
 #ifdef VECTORS4
 	typedef uint4 u;
 #elif defined VECTORS2

+ 53 - 30
driver-opencl.c

@@ -259,6 +259,15 @@ load_opencl_symbols() {
 #endif
 
 
+typedef cl_int (*queue_kernel_parameters_func_t)(_clState *, struct work *, cl_uint);
+
+struct opencl_kernel_interface {
+	const char *kiname;
+	const char *default_filename;
+	queue_kernel_parameters_func_t queue_kernel_parameters_func;
+};
+
+
 #ifdef HAVE_CURSES
 extern WINDOW *mainwin, *statuswin, *logwin;
 extern void enable_curses(void);
@@ -273,6 +282,7 @@ extern int gpur_thr_id;
 extern bool opt_noadl;
 extern bool have_opencl;
 static _clState *clStates[MAX_GPUDEVICES];
+static struct opencl_kernel_interface kernel_interfaces[];
 
 
 
@@ -369,7 +379,6 @@ _SET_INT_LIST(lookup_gap        , true, opt_lg )
 _SET_INT_LIST(thread_concurrency, true, opt_tc )
 #endif
 
-static
 enum cl_kernels select_kernel(const char * const arg)
 {
 	if (!strcmp(arg, "diablo"))
@@ -387,21 +396,44 @@ enum cl_kernels select_kernel(const char * const arg)
 	return KL_NONE;
 }
 
+const char *opencl_get_kernel_interface_name(const enum cl_kernels kern)
+{
+	struct opencl_kernel_interface *ki = &kernel_interfaces[kern];
+	return ki->kiname;
+}
+
+const char *opencl_get_default_kernel_filename(const enum cl_kernels kern)
+{
+	struct opencl_kernel_interface *ki = &kernel_interfaces[kern];
+	return ki->default_filename;
+}
+
 static
-bool _set_kernel(struct cgpu_info * const cgpu, const char * const _val)
+bool _set_kernel(struct cgpu_info * const cgpu, const char *_val)
 {
 	const enum cl_kernels kern = select_kernel(_val);
-	if (kern == KL_NONE)
-		return false;
 	struct opencl_device_data * const data = cgpu->device_data;
-	data->kernel = kern;
+	{
+		const char *kname = opencl_get_default_kernel_filename(kern);
+		if (kname)
+			_val = kname;
+	}
+	
+	size_t knamelen = strlen(_val);
+	char filename[knamelen + 3 + 1];
+	sprintf(filename, "%s.cl", _val);
+	
+	if (access(filename, R_OK))
+		return false;
+	
+	free(data->kernel_file);
+	data->kernel_file = strdup(_val);
+	
 	return true;
 }
 _SET_INTERFACE(kernel)
 const char *set_kernel(char *arg)
 {
-	if (opt_scrypt)
-		return "Cannot specify a kernel with scrypt";
 	return _set_list(arg, "Invalid value passed to set_kernel", _set_kernel);
 }
 #endif
@@ -1224,6 +1256,19 @@ cl_int queue_scrypt_kernel(_clState * const clState, struct work * const work, _
 #endif /* HAVE_OPENCL */
 
 
+static
+struct opencl_kernel_interface kernel_interfaces[] = {
+	{NULL},
+	{"poclbm",   "poclbm130302", queue_poclbm_kernel},
+	{"phatk",     "phatk121016", queue_phatk_kernel},
+	{"diakgcn", "diakgcn121016", queue_diakgcn_kernel},
+	{"diablo",   "diablo130302", queue_diablo_kernel},
+#ifdef USE_SCRYPT
+	{"scrypt",   "scrypt130511", queue_scrypt_kernel},
+#endif
+};
+
+
 #ifdef HAVE_OPENCL
 /* We have only one thread that ever re-initialises GPUs, thus if any GPU
  * init command fails due to a completely wedged GPU, the thread will never
@@ -1574,29 +1619,7 @@ static bool opencl_thread_prepare(struct thr_info *thr)
 	if (!cgpu->name)
 		cgpu->name = trimmed_strdup(name);
 	if (!cgpu->kname)
-	{
-		switch (clStates[i]->chosen_kernel) {
-			case KL_DIABLO:
-				cgpu->kname = "diablo";
-				break;
-			case KL_DIAKGCN:
-				cgpu->kname = "diakgcn";
-				break;
-			case KL_PHATK:
-				cgpu->kname = "phatk";
-				break;
-#ifdef USE_SCRYPT
-			case KL_SCRYPT:
-				cgpu->kname = "scrypt";
-				break;
-#endif
-			case KL_POCLBM:
-				cgpu->kname = "poclbm";
-				break;
-			default:
-				break;
-		}
-	}
+		cgpu->kname = opencl_get_kernel_interface_name(clStates[i]->chosen_kernel);
 	applog(LOG_INFO, "initCl() finished. Found %s", name);
 	get_now_datestamp(cgpu->init, sizeof(cgpu->init));
 

+ 4 - 1
driver-opencl.h

@@ -28,7 +28,7 @@ struct opencl_device_data {
 	
 	cl_uint vwidth;
 	size_t work_size;
-	enum cl_kernels kernel;
+	char *kernel_file;
 	cl_ulong max_alloc;
 	
 	enum opencl_binary_usage opt_opencl_binaries;
@@ -112,6 +112,9 @@ extern const char *set_shaders(char *arg);
 extern const char *set_lookup_gap(char *arg);
 extern const char *set_thread_concurrency(char *arg);
 #endif
+extern enum cl_kernels select_kernel(const char *);
+extern const char *opencl_get_kernel_interface_name(const enum cl_kernels);
+extern const char *opencl_get_default_kernel_filename(const enum cl_kernels);
 extern const char *set_kernel(char *arg);
 extern void write_config_opencl(FILE *);
 void manage_gpu(void);

+ 48 - 46
ocl.c

@@ -11,6 +11,7 @@
 #include "config.h"
 #ifdef HAVE_OPENCL
 
+#include <ctype.h>
 #include <signal.h>
 #include <stdbool.h>
 #include <stdint.h>
@@ -392,7 +393,7 @@ _clState *initCl(unsigned int gpu, char *name, size_t nameSize)
 	struct opencl_device_data * const data = cgpu->device_data;
 	cl_platform_id platform = NULL;
 	char pbuff[256], vbuff[255];
-	char *s;
+	char *s, *q;
 	cl_platform_id* platforms;
 	cl_uint preferred_vwidth;
 	cl_device_id *devices;
@@ -615,7 +616,8 @@ _clState *initCl(unsigned int gpu, char *name, size_t nameSize)
 	char filename[255];
 	char numbuf[32];
 
-	if (data->kernel == KL_NONE) {
+	if (!data->kernel_file)
+	{
 		if (opt_scrypt) {
 			applog(LOG_INFO, "Selecting scrypt kernel");
 			clState->chosen_kernel = KL_SCRYPT;
@@ -644,20 +646,51 @@ _clState *initCl(unsigned int gpu, char *name, size_t nameSize)
 			applog(LOG_INFO, "Selecting phatk kernel");
 			clState->chosen_kernel = KL_PHATK;
 		}
-		data->kernel = clState->chosen_kernel;
-	} else {
-		clState->chosen_kernel = data->kernel;
-		if (clState->chosen_kernel == KL_PHATK &&
-		    (strstr(vbuff, "844.4") || strstr(vbuff, "851.4") ||
-		     strstr(vbuff, "831.4") || strstr(vbuff, "898.1") ||
-		     strstr(vbuff, "923.1") || strstr(vbuff, "938.2") ||
-		     strstr(vbuff, "1113.2"))) {
-			applog(LOG_WARNING, "WARNING: You have selected the phatk kernel.");
-			applog(LOG_WARNING, "You are running SDK 2.6+ which performs poorly with this kernel.");
-			applog(LOG_WARNING, "Downgrade your SDK and delete any .bin files before starting again.");
-			applog(LOG_WARNING, "Or allow BFGMiner to automatically choose a more suitable kernel.");
-		}
+		data->kernel_file = strdup(opencl_get_default_kernel_filename(clState->chosen_kernel));
+	}
+	
+	snprintf(filename, sizeof(filename), "%s.cl", data->kernel_file);
+	snprintf(binaryfilename, sizeof(filename), "%s", data->kernel_file);
+	int pl;
+	char *source = file_contents(filename, &pl);
+	if (!source)
+		return NULL;
+	s = strstr(source, "kernel-interface:");
+	if (s)
+	{
+		for (s = &s[17]; s[0] && isspace(s[0]); ++s)
+			if (s[0] == '\n' || s[0] == '\r')
+				break;
+		for (q = s; q[0] && !isspace(q[0]); ++q)
+		{}  // Find end of string
+		const size_t kinamelen = q - s;
+		char kiname[kinamelen + 1];
+		memcpy(kiname, s, kinamelen);
+		kiname[kinamelen] = '\0';
+		clState->chosen_kernel = select_kernel(kiname);
+	}
+	switch (clState->chosen_kernel) {
+		case KL_NONE:
+			applog(LOG_ERR, "%s: Failed to identify kernel interface for %s",
+			       cgpu->dev_repr, data->kernel_file);
+			free(source);
+			return NULL;
+		case KL_PHATK:
+			if ((strstr(vbuff, "844.4") || strstr(vbuff, "851.4") ||
+			     strstr(vbuff, "831.4") || strstr(vbuff, "898.1") ||
+			     strstr(vbuff, "923.1") || strstr(vbuff, "938.2") ||
+			     strstr(vbuff, "1113.2"))) {
+				applog(LOG_WARNING, "WARNING: You have selected the phatk kernel.");
+				applog(LOG_WARNING, "You are running SDK 2.6+ which performs poorly with this kernel.");
+				applog(LOG_WARNING, "Downgrade your SDK and delete any .bin files before starting again.");
+				applog(LOG_WARNING, "Or allow BFGMiner to automatically choose a more suitable kernel.");
+			}
+		default:
+			;
 	}
+	applog(LOG_DEBUG, "%s: Using kernel %s with interface %s",
+	       cgpu->dev_repr, data->kernel_file,
+	       opencl_get_kernel_interface_name(clState->chosen_kernel));
 
 	/* For some reason 2 vectors is still better even if the card says
 	 * otherwise, and many cards lie about their max so use 256 as max
@@ -667,32 +700,6 @@ _clState *initCl(unsigned int gpu, char *name, size_t nameSize)
 	else if (preferred_vwidth > 2)
 		preferred_vwidth = 2;
 
-	switch (clState->chosen_kernel) {
-		case KL_POCLBM:
-			strcpy(filename, POCLBM_KERNNAME".cl");
-			strcpy(binaryfilename, POCLBM_KERNNAME);
-			break;
-		case KL_PHATK:
-			strcpy(filename, PHATK_KERNNAME".cl");
-			strcpy(binaryfilename, PHATK_KERNNAME);
-			break;
-		case KL_DIAKGCN:
-			strcpy(filename, DIAKGCN_KERNNAME".cl");
-			strcpy(binaryfilename, DIAKGCN_KERNNAME);
-			break;
-		case KL_SCRYPT:
-			strcpy(filename, SCRYPT_KERNNAME".cl");
-			strcpy(binaryfilename, SCRYPT_KERNNAME);
-			/* Scrypt only supports vector 1 */
-			data->vwidth = 1;
-			break;
-		case KL_NONE: /* Shouldn't happen */
-		case KL_DIABLO:
-			strcpy(filename, DIABLO_KERNNAME".cl");
-			strcpy(binaryfilename, DIABLO_KERNNAME);
-			break;
-	}
-
 	if (data->vwidth)
 		clState->vwidth = data->vwidth;
 	else {
@@ -741,16 +748,11 @@ _clState *initCl(unsigned int gpu, char *name, size_t nameSize)
 	FILE *binaryfile;
 	size_t *binary_sizes;
 	char **binaries;
-	int pl;
-	char *source = file_contents(filename, &pl);
 	size_t sourceSize[] = {(size_t)pl};
 	cl_uint slot, cpnd;
 
 	slot = cpnd = 0;
 
-	if (!source)
-		return NULL;
-
 	binary_sizes = calloc(sizeof(size_t) * MAX_GPUDEVICES * 4, 1);
 	if (unlikely(!binary_sizes)) {
 		applog(LOG_ERR, "Unable to calloc binary_sizes");

+ 2 - 0
phatk121016.cl

@@ -2,6 +2,8 @@
 // I have therefore decided to keep it public-domain.
 // Modified version copyright 2011-2012 Con Kolivas
 
+// kernel-interface: phatk
+
 #ifdef VECTORS4
 	typedef uint4 u;
 #elif defined VECTORS2

+ 2 - 0
poclbm130302.cl

@@ -5,6 +5,8 @@
 // This file is taken and modified from the public-domain poclbm project, and
 // we have therefore decided to keep it public-domain in Phoenix.
 
+// kernel-interface: poclbm
+
 #ifdef VECTORS4
 	typedef uint4 u;
 #elif defined VECTORS2

+ 2 - 0
scrypt130511.cl

@@ -28,6 +28,8 @@
  * online backup system.
  */
 
+// kernel-interface: scrypt
+
 __constant uint ES[2] = { 0x00FF00FF, 0xFF00FF00 };
 __constant uint K[] = {
 	0x428a2f98U,