diff --git a/pyopencl/__init__.py b/pyopencl/__init__.py index 2e7a0da77cfb1d7895f1232688c1bd9ea776a1e2..754549a12d9d11af995b73dbe6b57c9611d10a6f 100644 --- a/pyopencl/__init__.py +++ b/pyopencl/__init__.py @@ -26,7 +26,7 @@ THE SOFTWARE. import six import sys -from six.moves import input, range +from six.moves import input, range, intern from pyopencl.version import VERSION, VERSION_STATUS, VERSION_TEXT # noqa from pytools import Record as _Record @@ -426,16 +426,19 @@ def link_program(context, programs, options=[], devices=None): def _add_functionality(): cls_to_info_cls = { - _cl.Platform: (_cl.Platform.get_info, _cl.platform_info), - _cl.Device: (_cl.Device.get_info, _cl.device_info), - _cl.Context: (_cl.Context.get_info, _cl.context_info), - _cl.CommandQueue: (_cl.CommandQueue.get_info, _cl.command_queue_info), - _cl.Event: (_cl.Event.get_info, _cl.event_info), - _cl.MemoryObjectHolder: (MemoryObjectHolder.get_info, _cl.mem_info), - Image: (_cl.Image.get_image_info, _cl.image_info), - Program: (Program.get_info, _cl.program_info), - Kernel: (Kernel.get_info, _cl.kernel_info), - _cl.Sampler: (Sampler.get_info, _cl.sampler_info), + _cl.Platform: (_cl.Platform.get_info, _cl.platform_info, []), + _cl.Device: (_cl.Device.get_info, _cl.device_info, + ["PLATFORM", "MAX_WORK_GROUP_SIZE", "MAX_COMPUTE_UNITS"]), + _cl.Context: (_cl.Context.get_info, _cl.context_info, []), + _cl.CommandQueue: (_cl.CommandQueue.get_info, _cl.command_queue_info, + ["CONTEXT", "DEVICE"]), + _cl.Event: (_cl.Event.get_info, _cl.event_info, []), + _cl.MemoryObjectHolder: + (MemoryObjectHolder.get_info, _cl.mem_info, []), + Image: (_cl.Image.get_image_info, _cl.image_info, []), + Program: (Program.get_info, _cl.program_info, []), + Kernel: (Kernel.get_info, _cl.kernel_info, []), + _cl.Sampler: (Sampler.get_info, _cl.sampler_info, []), } def to_string(cls, value, default_format=None): @@ -454,19 +457,40 @@ def _add_functionality(): # {{{ get_info attributes ------------------------------------------------- - def make_getinfo(info_method, info_attr): + def make_getinfo(info_method, info_name, info_attr): def result(self): return info_method(self, info_attr) return property(result) - for cls, (info_method, info_class) in six.iteritems(cls_to_info_cls): + def make_cacheable_getinfo(info_method, info_name, cache_attr, info_attr): + def result(self): + try: + return getattr(self, cache_attr) + except AttributeError: + pass + + result = info_method(self, info_attr) + setattr(self, cache_attr, result) + return result + + return property(result) + + for cls, (info_method, info_class, cacheable_attrs) \ + in six.iteritems(cls_to_info_cls): for info_name, info_value in six.iteritems(info_class.__dict__): if info_name == "to_string" or info_name.startswith("_"): continue - setattr(cls, info_name.lower(), make_getinfo( - info_method, getattr(info_class, info_name))) + info_lower = info_name.lower() + info_constant = getattr(info_class, info_name) + if info_name in cacheable_attrs: + cache_attr = intern("_info_cache_"+info_lower) + setattr(cls, info_lower, make_cacheable_getinfo( + info_method, info_lower, cache_attr, info_constant)) + else: + setattr(cls, info_lower, make_getinfo( + info_method, info_name, info_constant)) # }}} @@ -624,6 +648,7 @@ def _add_functionality(): # {{{ Kernel kernel_old_init = Kernel.__init__ + kernel_old_get_work_group_info = Kernel.get_work_group_info def kernel_init(self, prg, name): if not isinstance(prg, _cl._Program): @@ -633,6 +658,17 @@ def _add_functionality(): self._source = getattr(prg, "_source", None) self._generate_naive_call() + self._wg_info_cache = {} + + def kernel_get_work_group_info(self, param, device): + try: + return self._wg_info_cache[param, device] + except KeyError: + pass + + result = kernel_old_get_work_group_info(self, param, device) + self._wg_info_cache[param, device] = result + return result # {{{ code generation for __call__, set_args @@ -935,6 +971,7 @@ def _add_functionality(): *args, **kwargs) Kernel.__init__ = kernel_init + Kernel.get_work_group_info = kernel_get_work_group_info Kernel._set_set_args_body = kernel__set_set_args_body Kernel._generate_buffer_arg_setter = kernel__generate_buffer_arg_setter Kernel._generate_bytes_arg_setter = kernel__generate_bytes_arg_setter