summaryrefslogtreecommitdiff
path: root/src/silx/opencl/processing.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/silx/opencl/processing.py')
-rw-r--r--src/silx/opencl/processing.py114
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