From d3af819c7aea574e361802f6acab09352994b80f Mon Sep 17 00:00:00 2001 From: Yichao Yu <yyc1992@gmail.com> Date: Tue, 20 May 2014 23:35:03 -0400 Subject: [PATCH] get_vec_info --- src/c_wrapper/utils.h | 161 ++++++++++++++++++++ src/c_wrapper/wrap_cl.cpp | 308 +++++++++++++------------------------- 2 files changed, 264 insertions(+), 205 deletions(-) create mode 100644 src/c_wrapper/utils.h diff --git a/src/c_wrapper/utils.h b/src/c_wrapper/utils.h new file mode 100644 index 00000000..95004880 --- /dev/null +++ b/src/c_wrapper/utils.h @@ -0,0 +1,161 @@ +#include "wrap_cl.h" +#include <string> +#include <sstream> +#include <string.h> +#include <memory> + +#define PYOPENCL_DEF_GET_CLASS_T(name) \ + static inline class_t \ + get_class_t() \ + { \ + return CLASS_##name; \ + } + + +template<class T> +static inline std::string +tostring(const T& v) +{ + std::ostringstream ostr; + ostr << v; + return ostr.str(); +} + + +template<typename T> +struct _D { + void operator()(T *p) { + free((void*)p); + } +}; + +template<typename T> +class pyopencl_buf : public std::unique_ptr<T, _D<T> > { + size_t m_len; +public: + pyopencl_buf(size_t len=1) : + std::unique_ptr<T, _D<T> >((T*)(len ? malloc(sizeof(T) * len) : NULL)), + m_len(len) + { + } + inline size_t + len() + { + return m_len; + } + inline T& + operator[](int i) + { + return this->get()[i]; + } + inline void + resize(size_t len) + { + if (len == m_len) + return; + m_len = len; + this->reset((T*)realloc((void*)this->release(), len * sizeof(T))); + } +}; + +template<> +class pyopencl_buf<void> : public std::unique_ptr<void, _D<void> > { + size_t m_len; +public: + pyopencl_buf(size_t len) : + std::unique_ptr<void, _D<void> >((len ? malloc(len) : NULL)), + m_len(len) + { + } + inline size_t + len() + { + return m_len; + } + inline void + resize(size_t len) + { + if (len == m_len) + return; + m_len = len; + this->reset(realloc(this->release(), len)); + } +}; + +namespace pyopencl { + +// FIXME +static inline char* +_copy_str(const std::string& str) +{ + return strdup(str.c_str()); +} + +template<typename T, typename... ArgTypes, typename... ArgTypes2> +static inline pyopencl_buf<T> +get_vec_info(cl_int (*func)(ArgTypes...), const char *name, + ArgTypes2&&... args) +{ + size_t size = 0; + call_guarded(func, name, args..., 0, NULL, &size); + pyopencl_buf<T> buf(size / sizeof(T)); + call_guarded(func, name, args..., size, buf.get(), &size); + return buf; +} +#define pyopencl_get_vec_info(type, what, args...) \ + pyopencl::get_vec_info<type>(clGet##what##Info, "clGet" #what "Info", args) + +template<typename T> +static inline generic_info +convert_array_info(const char *tname, pyopencl_buf<T> &buf) +{ + generic_info info; + info.dontfree = 0; + info.opaque_class = CLASS_NONE; + info.type = _copy_str(std::string(tname) + "[" + + tostring(buf.len()) + "]"); + info.value = buf.release(); + return info; +} + +template<typename T> +static inline generic_info +convert_array_info(const char *tname, pyopencl_buf<T> &&_buf) +{ + pyopencl_buf<T> &buf = _buf; + return convert_array_info<T>(tname, buf); +} + +#define pyopencl_convert_array_info(type, buf) \ + pyopencl::convert_array_info<type>(#type, buf) +#define pyopencl_get_array_info(type, what, args...) \ + pyopencl_convert_array_info(type, pyopencl_get_vec_info(type, what, args)) + +template<typename T, typename Cls> +static inline generic_info +convert_opaque_array_info(pyopencl_buf<T> &buf) +{ + pyopencl_buf<void*> ar(buf.len()); + for (unsigned i = 0;i < buf.len();i++) { + ar[i] = new Cls(buf[i]); + } + generic_info info; + info.dontfree = 0; + info.opaque_class = Cls::get_class_t(); + info.type = _copy_str(std::string("void*[") + tostring(buf.len()) + "]"); + info.value = ar.release(); + return info; +} + +template<typename T, typename Cls> +static inline generic_info +convert_opaque_array_info(pyopencl_buf<T> &&_buf) +{ + pyopencl_buf<T> &buf = _buf; + return convert_opaque_array_info<T, Cls>(buf); +} +#define pyopencl_get_opaque_array_info(type, cls, what, args...) \ + pyopencl::convert_opaque_array_info<type, cls>( \ + pyopencl_get_vec_info(type, what, args)) + +} diff --git a/src/c_wrapper/wrap_cl.cpp b/src/c_wrapper/wrap_cl.cpp index 933b9840..add2475e 100644 --- a/src/c_wrapper/wrap_cl.cpp +++ b/src/c_wrapper/wrap_cl.cpp @@ -1,32 +1,9 @@ -#include "wrap_cl.h" #include "error.h" +#include "utils.h" #include <stdlib.h> #include <vector> -#include <string.h> -#include <memory> -#include <sstream> -template<typename T> -struct _D { - void operator()(T *p) { - free((void*)p); - } -}; - -template<typename T> -class pyopencl_buf : public std::unique_ptr<T, _D<T> > { -public: - pyopencl_buf(size_t len=1) : - std::unique_ptr<T, _D<T> >(static_cast<T*>(malloc(sizeof(T) * len))) - { - } - inline T& - operator[](int i) - { - return this->get()[i]; - } -}; #define MALLOC(TYPE, VAR, N) TYPE *VAR = reinterpret_cast<TYPE*>(malloc(sizeof(TYPE)*(N))); @@ -83,19 +60,6 @@ public: // {{{ GetInfo helpers -#define PYOPENCL_GET_VEC_INFO(WHAT, FIRST_ARG, SECOND_ARG, RES_VEC) \ - { \ - size_t size; \ - pyopencl_call_guarded(clGet##WHAT##Info, \ - FIRST_ARG, SECOND_ARG, 0, NULL, &size); \ - \ - RES_VEC.resize(size / sizeof(RES_VEC.front())); \ - \ - pyopencl_call_guarded(clGet##WHAT##Info, \ - FIRST_ARG, SECOND_ARG, size, \ - RES_VEC.empty() ? NULL : &RES_VEC.front(), &size); \ - } - #define PYOPENCL_GET_OPAQUE_INFO(WHAT, FIRST_ARG, SECOND_ARG, CL_TYPE, TYPE, TYPEU) \ { \ CL_TYPE param_value; \ @@ -113,21 +77,6 @@ public: } -#define PYOPENCL_GET_OPAQUE_ARRAY_INFO(TYPE, CLS, CLSU, VEC) \ - { \ - pyopencl_buf<void*> ar(VEC.size()); \ - for(uint32_t i = 0; i < VEC.size(); ++i) { \ - ar[i] = new pyopencl::CLS(VEC[i]); \ - } \ - generic_info info; \ - info.dontfree = 0; \ - info.opaque_class = CLASS_##CLSU; \ - info.type = _copy_str(std::string("void*[") + tostring(VEC.size()) + "]"); \ - info.value = (void**)ar.release(); \ - return info; \ - } - - #define PYOPENCL_GET_STR_INFO(WHAT, FIRST_ARG, SECOND_ARG) \ { \ size_t param_value_size; \ @@ -160,20 +109,6 @@ public: return info; \ } -#define PYOPENCL_GET_ARRAY_INFO(TYPE, VEC) \ - { \ - pyopencl_buf<TYPE> ar(VEC.size()); \ - for(uint32_t i = 0; i < VEC.size(); ++i) { \ - ar[i] = VEC[i]; \ - } \ - generic_info info; \ - info.dontfree = 0; \ - info.opaque_class = CLASS_NONE; \ - info.type = _copy_str(std::string(#TYPE"[") + tostring(VEC.size()) + "]"); \ - info.value = (void*)ar.release(); \ - return info; \ - } - // }}} @@ -320,14 +255,6 @@ run_python_gc(); \ #define PYOPENCL_CL_IMAGE cl_mem #define PYOPENCL_CL_SAMPLER cl_sampler -template<class T> -std::string tostring(const T& v) -{ - std::ostringstream ostr; - ostr << v; - return ostr.str(); -} - // }}} namespace pyopencl @@ -340,13 +267,6 @@ cast_bool(const T &v) return v ? CL_TRUE : CL_FALSE; } - char *_copy_str(const std::string& str) { - MALLOC(char, cstr, str.size() + 1); - std::size_t len = str.copy(cstr, str.size()); - cstr[len] = '\0'; - return cstr; - } - class noncopyable { // non-copyable @@ -373,6 +293,7 @@ cast_bool(const T &v) cl_platform_id m_platform; public: + PYOPENCL_DEF_GET_CLASS_T(PLATFORM); platform(cl_platform_id pid) : m_platform(pid) { } @@ -442,6 +363,7 @@ cast_bool(const T &v) class device : public noncopyable { public: + PYOPENCL_DEF_GET_CLASS_T(DEVICE); enum reference_type_t { REF_NOT_OWNABLE, REF_FISSION_EXT, @@ -541,11 +463,8 @@ cast_bool(const T &v) case CL_DEVICE_MAX_WORK_GROUP_SIZE: DEV_GET_INT_INF(size_t); case CL_DEVICE_MAX_WORK_ITEM_SIZES: - { - std::vector<size_t> result; - PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result); - PYOPENCL_GET_ARRAY_INFO(size_t, result); - } + return pyopencl_get_array_info(size_t, Device, + m_device, param_name); case CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR: DEV_GET_INT_INF(cl_uint); case CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT: DEV_GET_INT_INF(cl_uint); @@ -637,11 +556,8 @@ cast_bool(const T &v) case CL_DEVICE_PARTITION_TYPES_EXT: case CL_DEVICE_AFFINITY_DOMAINS_EXT: case CL_DEVICE_PARTITION_STYLE_EXT: - { - std::vector<cl_device_partition_property_ext> result; - PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result); - PYOPENCL_GET_ARRAY_INFO(cl_device_partition_property_ext, result); - } + return pyopencl_get_array_info(cl_device_partition_property_ext, + Device, m_device, param_name); case CL_DEVICE_REFERENCE_COUNT_EXT: DEV_GET_INT_INF(cl_uint); #endif #if PYOPENCL_CL_VERSION >= 0x1020 @@ -655,17 +571,11 @@ cast_bool(const T &v) case CL_DEVICE_PARTITION_MAX_SUB_DEVICES: DEV_GET_INT_INF(cl_uint); case CL_DEVICE_PARTITION_TYPE: case CL_DEVICE_PARTITION_PROPERTIES: - { - std::vector<cl_device_partition_property> result; - PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result); - PYOPENCL_GET_ARRAY_INFO(cl_device_partition_property, result); - } + return pyopencl_get_array_info(cl_device_partition_property, + Device, m_device, param_name); case CL_DEVICE_PARTITION_AFFINITY_DOMAIN: - { - std::vector<cl_device_affinity_domain> result; - PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result); - PYOPENCL_GET_ARRAY_INFO(cl_device_affinity_domain, result); - } + return pyopencl_get_array_info(cl_device_affinity_domain, + Device, m_device, param_name); case CL_DEVICE_REFERENCE_COUNT: DEV_GET_INT_INF(cl_uint); case CL_DEVICE_PREFERRED_INTEROP_USER_SYNC: DEV_GET_INT_INF(cl_bool); case CL_DEVICE_PRINTF_BUFFER_SIZE: DEV_GET_INT_INF(cl_bool); @@ -688,11 +598,8 @@ cast_bool(const T &v) #endif #ifdef CL_DEVICE_GLOBAL_FREE_MEMORY_AMD case CL_DEVICE_GLOBAL_FREE_MEMORY_AMD: - { - std::vector<size_t> result; - PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result); - PYOPENCL_GET_ARRAY_INFO(size_t, result); - } + return pyopencl_get_array_info(size_t, Device, + m_device, param_name); #endif #ifdef CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD case CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD: DEV_GET_INT_INF(cl_uint); @@ -800,8 +707,6 @@ cast_bool(const T &v) // return py_result; // } // #endif - - }; // }}} @@ -815,6 +720,7 @@ cast_bool(const T &v) cl_context m_context; public: + PYOPENCL_DEF_GET_CLASS_T(CONTEXT); context(cl_context ctx, bool retain) : m_context(ctx) { @@ -843,37 +749,28 @@ cast_bool(const T &v) PYOPENCL_GET_INTEGRAL_INFO(Context, m_context, param_name, cl_uint); case CL_CONTEXT_DEVICES: - { - std::vector<cl_device_id> result; - PYOPENCL_GET_VEC_INFO(Context, m_context, param_name, result); - PYOPENCL_GET_OPAQUE_ARRAY_INFO(cl_device_id, device, DEVICE, result); - - } - - case CL_CONTEXT_PROPERTIES: - { - std::vector<cl_context_properties> result; - PYOPENCL_GET_VEC_INFO(Context, m_context, param_name, result); - - std::vector<generic_info> py_result; - - for (size_t i = 0; i < result.size(); i+=2) - { - cl_context_properties key = result[i]; - if(key == 0) - break; - generic_info info; - info.dontfree = 0; - info.opaque_class = CLASS_NONE; - switch (key) - { + return pyopencl_get_opaque_array_info( + cl_device_id, device, Context, m_context, param_name); + case CL_CONTEXT_PROPERTIES: { + auto result = pyopencl_get_vec_info( + cl_context_properties, Context, m_context, param_name); + pyopencl_buf<generic_info> py_result(result.len() / 2); + size_t i = 0; + for (;i < py_result.len();i++) { + cl_context_properties key = result[i * 2]; + if (key == 0) + break; + cl_context_properties value = result[i * 2 + 1]; + generic_info &info = py_result[i]; + info.dontfree = 0; + info.opaque_class = CLASS_NONE; + switch (key) { case CL_CONTEXT_PLATFORM: - { info.opaque_class = CLASS_PLATFORM; info.type = "void *"; - info.value = new platform(reinterpret_cast<cl_platform_id>(result[i+1])); + info.value = new platform( + reinterpret_cast<cl_platform_id>(value)); break; - } #if defined(PYOPENCL_GL_SHARING_VERSION) && (PYOPENCL_GL_SHARING_VERSION >= 1) #if defined(__APPLE__) && defined(HAVE_GL) @@ -885,22 +782,21 @@ cast_bool(const T &v) case CL_WGL_HDC_KHR: case CL_CGL_SHAREGROUP_KHR: #endif - info.type = "intptr_t *"; - info.value = (void*)result[i+1]; - // we do not own this object - info.dontfree = 1; - break; + info.type = "intptr_t *"; + info.value = (void*)value; + // we do not own this object + info.dontfree = 1; + break; #endif default: - throw error("Context.get_info", CL_INVALID_VALUE, - "unknown context_property key encountered"); - } - - py_result.push_back(info); + throw error("Context.get_info", CL_INVALID_VALUE, + "unknown context_property key encountered"); + } } - PYOPENCL_GET_ARRAY_INFO(generic_info, py_result); - } + py_result.resize(i); + return pyopencl_convert_array_info(generic_info, py_result); + } #if PYOPENCL_CL_VERSION >= 0x1010 case CL_CONTEXT_NUM_DEVICES: @@ -911,7 +807,6 @@ cast_bool(const T &v) throw error("Context.get_info", CL_INVALID_VALUE); } } - }; // }}} @@ -925,6 +820,7 @@ cast_bool(const T &v) cl_command_queue m_queue; public: + PYOPENCL_DEF_GET_CLASS_T(COMMAND_QUEUE); command_queue(cl_command_queue q, bool retain) : m_queue(q) { @@ -944,25 +840,24 @@ cast_bool(const T &v) cl_command_queue_properties props=0) { cl_device_id dev; - if (py_dev) - dev = py_dev->data(); - else - { - std::vector<cl_device_id> devs; - PYOPENCL_GET_VEC_INFO(Context, ctx.data(), CL_CONTEXT_DEVICES, devs); - if (devs.size() == 0) + if (py_dev) { + dev = py_dev->data(); + } else { + auto devs = pyopencl_get_vec_info(cl_device_id, Context, + ctx.data(), CL_CONTEXT_DEVICES); + if (devs.len() == 0) throw pyopencl::error("CommandQueue", CL_INVALID_VALUE, - "context doesn't have any devices? -- don't know which one to default to"); + "context doesn't have any devices? -- " + "don't know which one to default to"); dev = devs[0]; - } + } cl_int status_code; print_call_trace("clCreateCommandQueue"); - m_queue = clCreateCommandQueue( - ctx.data(), dev, props, &status_code); + m_queue = clCreateCommandQueue(ctx.data(), dev, props, &status_code); if (status_code != CL_SUCCESS) { - throw pyopencl::error("CommandQueue", status_code); + throw pyopencl::error("CommandQueue", status_code); } } @@ -1038,6 +933,7 @@ cast_bool(const T &v) cl_event m_event; public: + PYOPENCL_DEF_GET_CLASS_T(EVENT); event(cl_event event, bool retain) : m_event(event) { @@ -1308,6 +1204,7 @@ cast_bool(const T &v) class image : public memory_object { public: + PYOPENCL_DEF_GET_CLASS_T(IMAGE); image(cl_mem mem, bool retain, void *hostbuf=0) : memory_object(mem, retain, hostbuf) { } @@ -1360,21 +1257,21 @@ cast_bool(const T &v) // {{{ image formats - inline - generic_info get_supported_image_formats(context const &ctx, cl_mem_flags flags, cl_mem_object_type image_type) + inline generic_info + get_supported_image_formats(context const &ctx, cl_mem_flags flags, + cl_mem_object_type image_type) { cl_uint num_image_formats; pyopencl_call_guarded(clGetSupportedImageFormats, ctx.data(), flags, image_type, 0, NULL, &num_image_formats); - std::vector<cl_image_format> formats(num_image_formats); + pyopencl_buf<cl_image_format> formats(num_image_formats); pyopencl_call_guarded(clGetSupportedImageFormats, ctx.data(), flags, image_type, - formats.size(), - formats.empty( ) ? NULL : &formats.front(), NULL); + formats.len(), formats.get(), NULL); - PYOPENCL_GET_ARRAY_INFO(cl_image_format, formats); + return pyopencl_convert_array_info(cl_image_format, formats); } @@ -1725,6 +1622,7 @@ cast_bool(const T &v) class gl_buffer : public memory_object { public: + PYOPENCL_DEF_GET_CLASS_T(GL_BUFFER); gl_buffer(cl_mem mem, bool retain, void *hostbuf=0) : memory_object(mem, retain, hostbuf) { } @@ -1736,6 +1634,7 @@ cast_bool(const T &v) class gl_renderbuffer : public memory_object { public: + PYOPENCL_DEF_GET_CLASS_T(GL_RENDERBUFFER); gl_renderbuffer(cl_mem mem, bool retain, void *hostbuf=0) : memory_object(mem, retain, hostbuf) { } @@ -2022,6 +1921,7 @@ cast_bool(const T &v) class buffer : public memory_object { public: + PYOPENCL_DEF_GET_CLASS_T(BUFFER); buffer(cl_mem mem, bool retain, void *hostbuf=0) : memory_object(mem, retain, hostbuf) { } @@ -2118,6 +2018,7 @@ cast_bool(const T &v) cl_sampler m_sampler; public: + PYOPENCL_DEF_GET_CLASS_T(SAMPLER); sampler(context const &ctx, bool normalized_coordinates, cl_addressing_mode am, cl_filter_mode fm) { @@ -2189,6 +2090,7 @@ cast_bool(const T &v) program_kind_type m_program_kind; public: + PYOPENCL_DEF_GET_CLASS_T(PROGRAM); program(cl_program prog, bool retain, program_kind_type progkind=KND_UNKNOWN) : m_program(prog), m_program_kind(progkind) { @@ -2213,11 +2115,10 @@ cast_bool(const T &v) PYOPENCL_EQUALITY_TESTS(program); - std::vector<cl_device_id> get_info__devices() + pyopencl_buf<cl_device_id> get_info__devices() { - std::vector<cl_device_id> result; - PYOPENCL_GET_VEC_INFO(Program, m_program, CL_PROGRAM_DEVICES, result); - return result; + return pyopencl_get_vec_info(cl_device_id, Program, m_program, + CL_PROGRAM_DEVICES); } generic_info get_info(cl_program_info param_name) const @@ -2234,39 +2135,40 @@ cast_bool(const T &v) PYOPENCL_GET_INTEGRAL_INFO(Program, m_program, param_name, cl_uint); case CL_PROGRAM_DEVICES: - { - std::vector<cl_device_id> result; - PYOPENCL_GET_VEC_INFO(Program, m_program, param_name, result); - PYOPENCL_GET_OPAQUE_ARRAY_INFO(cl_device_id, device, DEVICE, result); - } + return pyopencl_get_opaque_array_info( + cl_device_id, device, Program, m_program, param_name); case CL_PROGRAM_SOURCE: PYOPENCL_GET_STR_INFO(Program, m_program, param_name); case CL_PROGRAM_BINARY_SIZES: - { - std::vector<size_t> result; - PYOPENCL_GET_VEC_INFO(Program, m_program, param_name, result); - PYOPENCL_GET_ARRAY_INFO(size_t, result); - } - case CL_PROGRAM_BINARIES: - { - std::vector<size_t> sizes; - PYOPENCL_GET_VEC_INFO(Program, m_program, CL_PROGRAM_BINARY_SIZES, sizes); - std::vector<char *> result_ptrs(sizes.size()); - for (unsigned i = 0; i < sizes.size(); ++i) { - result_ptrs[i] = new char[sizes[i]]; + return pyopencl_get_array_info(size_t, Program, m_program, + param_name); + case CL_PROGRAM_BINARIES: { + auto sizes = pyopencl_get_vec_info(size_t, Program, m_program, + CL_PROGRAM_BINARY_SIZES); + pyopencl_buf<char*> result_ptrs(sizes.len()); + for (size_t i = 0;i < sizes.len();i++) { + result_ptrs[i] = (char*)malloc(sizes[i]); } - std::vector<generic_info> gis(sizes.size()); - for(unsigned i = 0; i < sizes.size(); ++i) { - gis[i].opaque_class = CLASS_NONE; - gis[i].type = _copy_str(std::string("char[") + tostring(sizes[i]) + "]"); - gis[i].value = result_ptrs[i]; + try { + pyopencl_call_guarded(clGetProgramInfo, m_program, + CL_PROGRAM_BINARIES, + sizes.len() * sizeof(char*), + result_ptrs.get(), NULL); + } catch (...) { + for (size_t i = 0;i < sizes.len();i++) { + free(result_ptrs[i]); + } } - pyopencl_call_guarded(clGetProgramInfo, m_program, - CL_PROGRAM_BINARIES, - sizes.size() * sizeof(char *), - &result_ptrs.front(), NULL); - PYOPENCL_GET_ARRAY_INFO(generic_info, gis); - } + pyopencl_buf<generic_info> gis(sizes.len()); + for (size_t i = 0;i < sizes.len();i++) { + gis[i].value = result_ptrs[i]; + gis[i].dontfree = 0; + gis[i].opaque_class = CLASS_NONE; + gis[i].type = _copy_str(std::string("char[") + + tostring(sizes[i]) + "]"); + } + return pyopencl_convert_array_info(generic_info, gis); + } #if PYOPENCL_CL_VERSION >= 0x1020 case CL_PROGRAM_NUM_KERNELS: @@ -2459,6 +2361,7 @@ cast_bool(const T &v) cl_kernel m_kernel; public: + PYOPENCL_DEF_GET_CLASS_T(KERNEL); kernel(cl_kernel knl, bool retain) : m_kernel(knl) { @@ -2587,13 +2490,8 @@ cast_bool(const T &v) PYOPENCL_FIRST_ARG, param_name, size_t); case CL_KERNEL_COMPILE_WORK_GROUP_SIZE: - { - std::vector<size_t> result; - PYOPENCL_GET_VEC_INFO(KernelWorkGroup, - PYOPENCL_FIRST_ARG, param_name, result); - - PYOPENCL_GET_ARRAY_INFO(size_t, result); - } + return pyopencl_get_array_info(size_t, KernelWorkGroup, + m_kernel, dev.data(), param_name); case CL_KERNEL_LOCAL_MEM_SIZE: #if PYOPENCL_CL_VERSION >= 0x1010 case CL_KERNEL_PRIVATE_MEM_SIZE: -- GitLab