[Beignet] [PATCH v2] runtime: relax max group restrications.

Zhigang Gong zhigang.gong at intel.com
Sun Jun 29 19:29:38 PDT 2014


From: Zhigang Gong <zhigang.gong at linux.intel.com>

If the kernel doesn't use slm/barrier, there is no hard limitation
for the max group size. And if the max work group size is more than
1024, the original 64 urb entry count will not be sufficient to hold
all the curbe payload. Change the entry count to max thread count to
fix this potential issue.

I found this bug when I tried to run phoronix test suite's juliagpu
test case on my MBA.

v2:
refine the max kernel work group size calculation mechanism.
the wg_sz should not be a device's member variable, it should be
a variable derived from kernel and device's attriute at runtime.

Signed-off-by: Zhigang Gong <zhigang.gong at linux.intel.com>
---
 src/cl_command_queue_gen7.c |  6 ------
 src/cl_device_id.c          | 43 ++++++++++++++++++++++++++++++++-----------
 src/cl_device_id.h          |  2 +-
 src/cl_kernel.c             |  2 +-
 src/intel/intel_gpgpu.c     |  2 +-
 5 files changed, 35 insertions(+), 20 deletions(-)

diff --git a/src/cl_command_queue_gen7.c b/src/cl_command_queue_gen7.c
index 9af4829..5b80d74 100644
--- a/src/cl_command_queue_gen7.c
+++ b/src/cl_command_queue_gen7.c
@@ -304,12 +304,6 @@ cl_command_queue_ND_range_gen7(cl_command_queue queue,
   kernel.thread_n = thread_n = (local_sz + simd_sz - 1) / simd_sz;
   kernel.curbe_sz = cst_sz;
 
-  /* Barrier and SLM must fit into a single half slice */
-  if(kernel.use_slm > 0 && simd_sz == 8 && local_sz > MAX_GROUP_SIZE_IN_HALFSLICE){
-    fprintf(stderr, "Beignet: Work group CAN NOT large than %d when using barrier or local momery.\n", MAX_GROUP_SIZE_IN_HALFSLICE);
-    return CL_OUT_OF_RESOURCES;
-  }
-
   if (scratch_sz > ker->program->ctx->device->scratch_mem_size) {
     fprintf(stderr, "Beignet: Out of scratch memory %d.\n", scratch_sz);
     return CL_OUT_OF_RESOURCES;
diff --git a/src/cl_device_id.c b/src/cl_device_id.c
index 0263f02..41f371d 100644
--- a/src/cl_device_id.c
+++ b/src/cl_device_id.c
@@ -36,6 +36,8 @@
 #define CL_DEVICE_BUILT_IN_KERNELS 0x103F
 #endif
 
+#define MAX_CL_KERNEL_WORK_GROUP_SIZE 2048
+
 static struct _cl_device_id intel_ivb_gt2_device = {
   INIT_ICD(dispatch)
   .max_compute_unit = 16,
@@ -43,7 +45,6 @@ static struct _cl_device_id intel_ivb_gt2_device = {
   .max_work_item_sizes = {512, 512, 512},
   .max_work_group_size = 1024,
   .max_clock_frequency = 1000,
-  .wg_sz = 1024,
 #include "cl_gen7_device.h"
 };
 
@@ -54,7 +55,6 @@ static struct _cl_device_id intel_ivb_gt1_device = {
   .max_work_item_sizes = {512, 512, 512},
   .max_work_group_size = 512,
   .max_clock_frequency = 1000,
-  .wg_sz = 512,
 #include "cl_gen7_device.h"
 };
 
@@ -65,7 +65,6 @@ static struct _cl_device_id intel_baytrail_t_device = {
   .max_work_item_sizes = {512, 512, 512},
   .max_work_group_size = 256,
   .max_clock_frequency = 1000,
-  .wg_sz = 256,
 #include "cl_gen7_device.h"
 };
 
@@ -77,7 +76,6 @@ static struct _cl_device_id intel_hsw_gt1_device = {
   .max_work_item_sizes = {512, 512, 512},
   .max_work_group_size = 512,
   .max_clock_frequency = 1000,
-  .wg_sz = 512,
 #include "cl_gen75_device.h"
 };
 
@@ -88,7 +86,6 @@ static struct _cl_device_id intel_hsw_gt2_device = {
   .max_work_item_sizes = {512, 512, 512},
   .max_work_group_size = 1024,
   .max_clock_frequency = 1000,
-  .wg_sz = 1024,
 #include "cl_gen75_device.h"
 };
 
@@ -99,7 +96,6 @@ static struct _cl_device_id intel_hsw_gt3_device = {
   .max_work_item_sizes = {512, 512, 512},
   .max_work_group_size = 1024,
   .max_clock_frequency = 1000,
-  .wg_sz = 2048,
 #include "cl_gen75_device.h"
 };
 
@@ -465,6 +461,20 @@ cl_device_get_version(cl_device_id device, cl_int *ver)
   _DECL_FIELD(FIELD)
 
 #include "cl_kernel.h"
+#include "cl_program.h"
+
+LOCAL size_t
+cl_get_kernel_max_wg_sz(cl_kernel kernel)
+{
+  size_t work_group_size;
+  if (!interp_kernel_use_slm(kernel->opaque))
+    work_group_size = MAX_CL_KERNEL_WORK_GROUP_SIZE;
+  else
+    work_group_size = kernel->program->ctx->device->max_work_group_size *
+                      (interp_kernel_get_simd_width(kernel->opaque) / 8);
+  return work_group_size;
+}
+
 LOCAL cl_int
 cl_get_kernel_workgroup_info(cl_kernel kernel,
                              cl_device_id device,
@@ -484,13 +494,24 @@ cl_get_kernel_workgroup_info(cl_kernel kernel,
 
   CHECK_KERNEL(kernel);
   switch (param_name) {
-    DECL_FIELD(WORK_GROUP_SIZE, device->wg_sz)
+    case CL_KERNEL_WORK_GROUP_SIZE:
+    {
+      if (param_value && param_value_size < sizeof(size_t))
+        return CL_INVALID_VALUE;
+      if (param_value_size_ret != NULL)
+        *param_value_size_ret = sizeof(size_t);
+      if (param_value) {
+        size_t work_group_size = cl_get_kernel_max_wg_sz(kernel);
+        *(size_t*)param_value = work_group_size;
+        return CL_SUCCESS;
+      }
+    }
     DECL_FIELD(PREFERRED_WORK_GROUP_SIZE_MULTIPLE, device->preferred_wg_sz_mul)
     case CL_KERNEL_LOCAL_MEM_SIZE:
-      {
-        size_t local_mem_sz =  interp_kernel_get_slm_size(kernel->opaque) + kernel->local_mem_sz;
-        _DECL_FIELD(local_mem_sz)
-      }
+    {
+      size_t local_mem_sz =  interp_kernel_get_slm_size(kernel->opaque) + kernel->local_mem_sz;
+      _DECL_FIELD(local_mem_sz)
+    }
     DECL_FIELD(COMPILE_WORK_GROUP_SIZE, kernel->compile_wg_sz)
     DECL_FIELD(PRIVATE_MEM_SIZE, kernel->stack_size)
     default:
diff --git a/src/cl_device_id.h b/src/cl_device_id.h
index 422ef37..9f8f26f 100644
--- a/src/cl_device_id.h
+++ b/src/cl_device_id.h
@@ -101,7 +101,6 @@ struct _cl_device_id {
   size_t driver_version_sz;
   size_t built_in_kernels_sz;
   /* Kernel specific info that we're assigning statically */
-  size_t wg_sz;
   size_t preferred_wg_sz_mul;
   /* SubDevice specific info */
   cl_device_id parent_device;
@@ -137,6 +136,7 @@ extern cl_int cl_get_kernel_workgroup_info(cl_kernel kernel,
                                            size_t *         param_value_size_ret);
 /* Returns the Gen device ID */
 extern cl_int cl_device_get_version(cl_device_id device, cl_int *ver);
+extern size_t cl_get_kernel_max_wg_sz(cl_kernel);
 
 #endif /* __CL_DEVICE_ID_H__ */
 
diff --git a/src/cl_kernel.c b/src/cl_kernel.c
index 5d0b36e..aad3c04 100644
--- a/src/cl_kernel.c
+++ b/src/cl_kernel.c
@@ -410,7 +410,7 @@ cl_kernel_work_group_sz(cl_kernel ker,
   for (i = 1; i < wk_dim; ++i)
     sz *= local_wk_sz[i];
 
-  if (sz > ker->program->ctx->device->max_work_group_size) {
+  if (sz > cl_get_kernel_max_wg_sz(ker)) {
     err = CL_INVALID_WORK_ITEM_SIZE;
     goto error;
   }
diff --git a/src/intel/intel_gpgpu.c b/src/intel/intel_gpgpu.c
index 3b89539..5decdfc 100644
--- a/src/intel/intel_gpgpu.c
+++ b/src/intel/intel_gpgpu.c
@@ -577,7 +577,7 @@ intel_gpgpu_state_init(intel_gpgpu_t *gpgpu,
   gpgpu->sampler_bitmap = ~((1 << max_sampler_n) - 1);
 
   /* URB */
-  gpgpu->urb.num_cs_entries = 64;
+  gpgpu->urb.num_cs_entries = max_threads;
   gpgpu->urb.size_cs_entry = size_cs_entry;
   gpgpu->max_threads = max_threads;
 
-- 
1.8.3.2



More information about the Beignet mailing list