From 71383294df4b7f49b1fe02f8d322901dfed7a114 Mon Sep 17 00:00:00 2001
From: Yifan Zhao <yifanz16@illinois.edu>
Date: Thu, 23 Jan 2020 18:46:26 -0600
Subject: [PATCH] Look for device by name in opencl

---
 hpvm/projects/hpvm-rt/hpvm-rt.cpp | 221 ++++++++++++++++++++++++++++--
 1 file changed, 208 insertions(+), 13 deletions(-)

diff --git a/hpvm/projects/hpvm-rt/hpvm-rt.cpp b/hpvm/projects/hpvm-rt/hpvm-rt.cpp
index cb3206ef50..266d6296dc 100644
--- a/hpvm/projects/hpvm-rt/hpvm-rt.cpp
+++ b/hpvm/projects/hpvm-rt/hpvm-rt.cpp
@@ -1,4 +1,5 @@
 #include <CL/cl.h>
+#include <algorithm>
 #include <cassert>
 #include <cstdio>
 #include <cstdlib>
@@ -24,8 +25,6 @@
 
 #define BILLION 1000000000LL
 
-using namespace std;
-
 typedef struct {
   pthread_t threadID;
   std::vector<pthread_t> *threads;
@@ -60,10 +59,152 @@ pthread_mutex_t ocl_mtx;
 #define NUM_TESTS 1
 hpvm_TimerSet kernel_timer;
 
+static const char *getErrorString(cl_int error) {
+  switch (error) {
+  // run-time and JIT compiler errors
+  case 0:
+    return "CL_SUCCESS";
+  case -1:
+    return "CL_DEVICE_NOT_FOUND";
+  case -2:
+    return "CL_DEVICE_NOT_AVAILABLE";
+  case -3:
+    return "CL_COMPILER_NOT_AVAILABLE";
+  case -4:
+    return "CL_MEM_OBJECT_ALLOCATION_FAILURE";
+  case -5:
+    return "CL_OUT_OF_RESOURCES";
+  case -6:
+    return "CL_OUT_OF_HOST_MEMORY";
+  case -7:
+    return "CL_PROFILING_INFO_NOT_AVAILABLE";
+  case -8:
+    return "CL_MEM_COPY_OVERLAP";
+  case -9:
+    return "CL_IMAGE_FORMAT_MISMATCH";
+  case -10:
+    return "CL_IMAGE_FORMAT_NOT_SUPPORTED";
+  case -11:
+    return "CL_BUILD_PROGRAM_FAILURE";
+  case -12:
+    return "CL_MAP_FAILURE";
+  case -13:
+    return "CL_MISALIGNED_SUB_BUFFER_OFFSET";
+  case -14:
+    return "CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST";
+  case -15:
+    return "CL_COMPILE_PROGRAM_FAILURE";
+  case -16:
+    return "CL_LINKER_NOT_AVAILABLE";
+  case -17:
+    return "CL_LINK_PROGRAM_FAILURE";
+  case -18:
+    return "CL_DEVICE_PARTITION_FAILED";
+  case -19:
+    return "CL_KERNEL_ARG_INFO_NOT_AVAILABLE";
+
+  // compile-time errors
+  case -30:
+    return "CL_INVALID_VALUE";
+  case -31:
+    return "CL_INVALID_DEVICE_TYPE";
+  case -32:
+    return "CL_INVALID_PLATFORM";
+  case -33:
+    return "CL_INVALID_DEVICE";
+  case -34:
+    return "CL_INVALID_CONTEXT";
+  case -35:
+    return "CL_INVALID_QUEUE_PROPERTIES";
+  case -36:
+    return "CL_INVALID_COMMAND_QUEUE";
+  case -37:
+    return "CL_INVALID_HOST_PTR";
+  case -38:
+    return "CL_INVALID_MEM_OBJECT";
+  case -39:
+    return "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR";
+  case -40:
+    return "CL_INVALID_IMAGE_SIZE";
+  case -41:
+    return "CL_INVALID_SAMPLER";
+  case -42:
+    return "CL_INVALID_BINARY";
+  case -43:
+    return "CL_INVALID_BUILD_OPTIONS";
+  case -44:
+    return "CL_INVALID_PROGRAM";
+  case -45:
+    return "CL_INVALID_PROGRAM_EXECUTABLE";
+  case -46:
+    return "CL_INVALID_KERNEL_NAME";
+  case -47:
+    return "CL_INVALID_KERNEL_DEFINITION";
+  case -48:
+    return "CL_INVALID_KERNEL";
+  case -49:
+    return "CL_INVALID_ARG_INDEX";
+  case -50:
+    return "CL_INVALID_ARG_VALUE";
+  case -51:
+    return "CL_INVALID_ARG_SIZE";
+  case -52:
+    return "CL_INVALID_KERNEL_ARGS";
+  case -53:
+    return "CL_INVALID_WORK_DIMENSION";
+  case -54:
+    return "CL_INVALID_WORK_GROUP_SIZE";
+  case -55:
+    return "CL_INVALID_WORK_ITEM_SIZE";
+  case -56:
+    return "CL_INVALID_GLOBAL_OFFSET";
+  case -57:
+    return "CL_INVALID_EVENT_WAIT_LIST";
+  case -58:
+    return "CL_INVALID_EVENT";
+  case -59:
+    return "CL_INVALID_OPERATION";
+  case -60:
+    return "CL_INVALID_GL_OBJECT";
+  case -61:
+    return "CL_INVALID_BUFFER_SIZE";
+  case -62:
+    return "CL_INVALID_MIP_LEVEL";
+  case -63:
+    return "CL_INVALID_GLOBAL_WORK_SIZE";
+  case -64:
+    return "CL_INVALID_PROPERTY";
+  case -65:
+    return "CL_INVALID_IMAGE_DESCRIPTOR";
+  case -66:
+    return "CL_INVALID_COMPILER_OPTIONS";
+  case -67:
+    return "CL_INVALID_LINKER_OPTIONS";
+  case -68:
+    return "CL_INVALID_DEVICE_PARTITION_COUNT";
+
+  // extension errors
+  case -1000:
+    return "CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR";
+  case -1001:
+    return "CL_PLATFORM_NOT_FOUND_KHR";
+  case -1002:
+    return "CL_INVALID_D3D10_DEVICE_KHR";
+  case -1003:
+    return "CL_INVALID_D3D10_RESOURCE_KHR";
+  case -1004:
+    return "CL_D3D10_RESOURCE_ALREADY_ACQUIRED_KHR";
+  case -1005:
+    return "CL_D3D10_RESOURCE_NOT_ACQUIRED_KHR";
+  default:
+    return "Unknown OpenCL error";
+  }
+}
+
 static inline void checkErr(cl_int err, cl_int success, const char *name) {
   if (err != success) {
     cout << "ERROR: " << name << flush << "\n";
-    cout << "ErrorCode: " << err << flush << "\n";
+    cout << "ErrorCode: " << getErrorString(err) << flush << "\n";
     exit(EXIT_FAILURE);
   }
 }
@@ -1210,6 +1351,61 @@ void llvm_hpvm_x86_wait(void *graphID) {
   DEBUG(cout << "\t... pthread Done!\n");
 }
 
+// Returns the platform name.
+std::string getPlatformName(cl_platform_id pid) {
+  cl_int status;
+
+  size_t sz;
+  status = clGetPlatformInfo(pid, CL_PLATFORM_NAME, 0, NULL, &sz);
+  checkErr(status, CL_SUCCESS, "Query for platform name size failed");
+
+  char *name = new char[sz];
+  status = clGetPlatformInfo(pid, CL_PLATFORM_NAME, sz, name, NULL);
+  checkErr(status, CL_SUCCESS, "Query for platform name failed");
+
+  const auto &tmp = std::string(name, name + sz);
+  delete[] name;
+  return tmp;
+}
+
+// Searches all platforms for the first platform whose name
+// contains the search string (case-insensitive).
+cl_platform_id findPlatform(const char *platform_name_search) {
+  cl_int status;
+
+  std::string search = platform_name_search;
+  std::transform(search.begin(), search.end(), search.begin(), ::tolower);
+
+  // Get number of platforms.
+  cl_uint num_platforms;
+  status = clGetPlatformIDs(0, NULL, &num_platforms);
+  checkErr(status, CL_SUCCESS, "Query for number of platforms failed");
+
+  // Get a list of all platform ids.
+  cl_platform_id *pids =
+      (cl_platform_id *)malloc(sizeof(cl_platform_id) * num_platforms);
+  status = clGetPlatformIDs(num_platforms, pids, NULL);
+  checkErr(status, CL_SUCCESS, "Query for all platform ids failed");
+
+  // For each platform, get name and compare against the search string.
+  for (unsigned i = 0; i < num_platforms; ++i) {
+    std::string name = getPlatformName(pids[i]);
+
+    // Convert to lower case.
+    std::transform(name.begin(), name.end(), name.begin(), ::tolower);
+
+    if (name.find(search) != std::string::npos) {
+      // Found!
+      free(pids);
+      return pids[i];
+    }
+  }
+
+  free(pids);
+  // No platform found.
+  assert(false && "No matching platform found!");
+}
+
 void *llvm_hpvm_ocl_initContext(enum hpvm::Target T) {
   pthread_mutex_lock(&ocl_mtx);
   DEBUG(std::string Target = T == hpvm::GPU_TARGET ? "GPU" : "SPIR");
@@ -1240,20 +1436,19 @@ void *llvm_hpvm_ocl_initContext(enum hpvm::Target T) {
                       NULL);
     DEBUG(cout << "\tEXTENSIONS = " << buffer << flush << "\n");
   }
-  // set platform property - just pick the first one
-  // cl_context_properties properties[] = {CL_CONTEXT_PLATFORM,
-  //(long) platforms[0],
-  // 0};
-  // globalOCLContext = clCreateContextFromType(properties, CL_DEVICE_TYPE_GPU,
-  // NULL, NULL, &errcode);
-  // assert(numPlatforms >= 2 && "Expecting two OpenCL platforms");
-  // Choose second one which is X86 AVX
-  cl_context_properties properties[] = {
-      CL_CONTEXT_PLATFORM, (long)platforms[T == hpvm::GPU_TARGET ? 0 : 1], 0};
+  cl_platform_id platformId;
+  if (T == hpvm::GPU_TARGET) {
+    platformId = findPlatform("nvidia");
+  } else {
+    platformId = findPlatform("intel");
+  }
+  cl_context_properties properties[] = {CL_CONTEXT_PLATFORM, (long)platformId,
+                                        0};
   globalOCLContext = clCreateContextFromType(
       properties,
       T == hpvm::GPU_TARGET ? CL_DEVICE_TYPE_GPU : CL_DEVICE_TYPE_CPU, NULL,
       NULL, &errcode);
+  checkErr(errcode, CL_SUCCESS, "Failure to create context");
   // get the list of OCL devices associated with context
   size_t dataBytes;
   errcode = clGetContextInfo(globalOCLContext, CL_CONTEXT_DEVICES, 0, NULL,
-- 
GitLab