diff options
Diffstat (limited to 'src/silx/opencl/processing.py')
-rw-r--r-- | src/silx/opencl/processing.py | 114 |
1 files changed, 78 insertions, 36 deletions
diff --git a/src/silx/opencl/processing.py b/src/silx/opencl/processing.py index 8b81f7f..c223354 100644 --- a/src/silx/opencl/processing.py +++ b/src/silx/opencl/processing.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- # # Project: S I L X project # https://github.com/silx-kit/silx @@ -38,7 +37,7 @@ __author__ = "Jerome Kieffer" __contact__ = "Jerome.Kieffer@ESRF.eu" __license__ = "MIT" __copyright__ = "European Synchrotron Radiation Facility, Grenoble, France" -__date__ = "02/03/2021" +__date__ = "06/10/2022" __status__ = "stable" import sys @@ -53,7 +52,8 @@ from .utils import concatenate_cl_kernel import platform BufferDescription = namedtuple("BufferDescription", ["name", "size", "dtype", "flags"]) -EventDescription = namedtuple("EventDescription", ["name", "event"]) +EventDescription = namedtuple("EventDescription", ["name", "event"]) # Deprecated, please use ProfileDescription +ProfileDescription = namedtuple("ProfileDescription", ["name", "start", "stop"]) logger = logging.getLogger(__name__) @@ -286,6 +286,7 @@ class OpenclProcessing(object): self.kernels = None self.program = None +# Methods about Profiling def set_profiling(self, value=True): """Switch On/Off the profiling flag of the command queue to allow debugging @@ -309,37 +310,42 @@ class OpenclProcessing(object): """ Add an OpenCL event to the events lists, if profiling is enabled. - :param event: silx.opencl.processing.EventDescription. + :param event: pyopencl.NanyEvent. :param desc: event description """ if self.profile: - self.events.append(EventDescription(desc, event)) - - def allocate_texture(self, shape, hostbuf=None, support_1D=False): - return allocate_texture(self.ctx, shape, hostbuf=hostbuf, support_1D=support_1D) + try: + profile = event.profile + self.events.append(ProfileDescription(desc, profile.start, profile.end)) + except Exception: + # Probably the driver does not support profiling + pass - def transfer_to_texture(self, arr, tex_ref): + def profile_multi(self, event_lists): """ - Transfer an array to a texture. + Extract profiling info from several OpenCL event, if profiling is enabled. - :param arr: Input array. Can be a numpy array or a pyopencl array. - :param tex_ref: texture reference (pyopencl._cl.Image). + :param event_lists: list of ("desc", pyopencl.NanyEvent). """ - copy_args = [self.queue, tex_ref, arr] - shp = arr.shape - ndim = arr.ndim - if ndim == 1: - # pyopencl and OpenCL < 1.2 do not support image1d_t - # force 2D with one row in this case - # ~ ndim = 2 - shp = (1,) + shp - copy_kwargs = {"origin":(0,) * ndim, "region": shp[::-1]} - if not(isinstance(arr, numpy.ndarray)): # assuming pyopencl.array.Array - # D->D copy - copy_args[2] = arr.data - copy_kwargs["offset"] = 0 - ev = pyopencl.enqueue_copy(*copy_args, **copy_kwargs) - self.profile_add(ev, "Transfer to texture") + if self.profile: + for event_desc in event_lists: + if isinstance(event_desc, ProfileDescription): + self.events.append(event_desc) + else: + if isinstance(event_desc, EventDescription) or "__len__" in dir(e) and len(e) == 2: + desc, event = event_desc + else: + desc = "?" + event = event_desc + try: + profile = event.profile + start = profile.start + end = profile.end + except Exception: + # probably an unfinished job ... use old-style. + self.events.append(event_desc) + else: + self.events.append(ProfileDescription(desc, start, end)) def log_profile(self, stats=False): """If we are in profiling mode, prints out all timing for every single OpenCL call @@ -359,20 +365,29 @@ class OpenclProcessing(object): if self.profile: for e in self.events: - if "__len__" in dir(e) and len(e) >= 2: + if isinstance(e, ProfileDescription): + name = e[0] + t0 = e[1] + t1 = e[2] + elif isinstance(e, EventDescription) or "__len__" in dir(e) and len(e) == 2: name = e[0] pr = e[1].profile t0 = pr.start t1 = pr.end - et = 1e-6 * (t1 - t0) - total_time += et - if stats is None: - out.append(f"{name:>50} : {et:.3f}ms") + else: + name = "?" + t0 = e.profile.start + t1 = e.profile.end + + et = 1e-6 * (t1 - t0) + total_time += et + if stats is None: + out.append(f"{name:>50} : {et:.3f}ms") + else: + if name in stats: + stats[name].append(et) else: - if name in stats: - stats[name].append(et) - else: - stats[name] = [et] + stats[name] = [et] if stats is not None: for k, v in stats.items(): n = numpy.array(v) @@ -390,6 +405,33 @@ class OpenclProcessing(object): with self.sem: self.events = [] +# Methods about textures + def allocate_texture(self, shape, hostbuf=None, support_1D=False): + return allocate_texture(self.ctx, shape, hostbuf=hostbuf, support_1D=support_1D) + + def transfer_to_texture(self, arr, tex_ref): + """ + Transfer an array to a texture. + + :param arr: Input array. Can be a numpy array or a pyopencl array. + :param tex_ref: texture reference (pyopencl._cl.Image). + """ + copy_args = [self.queue, tex_ref, arr] + shp = arr.shape + ndim = arr.ndim + if ndim == 1: + # pyopencl and OpenCL < 1.2 do not support image1d_t + # force 2D with one row in this case + # ~ ndim = 2 + shp = (1,) + shp + copy_kwargs = {"origin":(0,) * ndim, "region": shp[::-1]} + if not(isinstance(arr, numpy.ndarray)): # assuming pyopencl.array.Array + # D->D copy + copy_args[2] = arr.data + copy_kwargs["offset"] = 0 + ev = pyopencl.enqueue_copy(*copy_args, **copy_kwargs) + self.profile_add(ev, "Transfer to texture") + @property def x87_volatile_option(self): # this is running 32 bits OpenCL woth POCL |