From 8c3939f6c97a8fff0b12e310f5e1cfee6a6ac06e Mon Sep 17 00:00:00 2001 From: Jerome Kieffer Date: Tue, 2 Dec 2025 08:53:41 +0100 Subject: [PATCH 1/8] clean up one test --- src/silx/conftest.py | 8 +++++++- src/silx/io/test/test_nxdata.py | 9 ++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/silx/conftest.py b/src/silx/conftest.py index 0a6a84e6d0..7be088750e 100644 --- a/src/silx/conftest.py +++ b/src/silx/conftest.py @@ -77,12 +77,18 @@ def pytest_configure(config): "ignore:Non-empty compiler output encountered. Set the environment variable PYOPENCL_COMPILER_OUTPUT=1 to see more.:UserWarning", # Remove __array__ ignore once h5py v3.12 is released "ignore:__array__ implementation doesn't accept a copy keyword, so passing copy=False failed. __array__ must implement 'dtype' and 'copy' keyword arguments.:DeprecationWarning", - "ignore::pyopencl.RepeatedKernelRetrieval", # Deprecated pyparsing usage in matplotlib: https://github.com/matplotlib/matplotlib/issues/30617 "ignore::DeprecationWarning:matplotlib._fontconfig_pattern", "ignore::DeprecationWarning:matplotlib._mathtext", "ignore::DeprecationWarning:pyparsing.util", ) +try: + import pyopencl +except: + pass +else: + if "RepeatedKernelRetrieval" in dir(pyopencl): + _FILTERWARNINGS = _FILTERWARNINGS + ("ignore::pyopencl.RepeatedKernelRetrieval",) def pytest_collection_modifyitems(items): diff --git a/src/silx/io/test/test_nxdata.py b/src/silx/io/test/test_nxdata.py index baec00c269..e7e77a1897 100644 --- a/src/silx/io/test/test_nxdata.py +++ b/src/silx/io/test/test_nxdata.py @@ -24,9 +24,10 @@ __authors__ = ["P. Knobel"] __license__ = "MIT" -__date__ = "24/03/2020" +__date__ = "02/12/2025" +import os import tempfile import unittest @@ -490,6 +491,12 @@ def setUp(self): tmp.file.close() self.h5fname = tmp.name + def tearDown(self): + try: + os.unlink(self.h5fname) + except Exception as err: + print(f"{type(err).__name__}: {err}\nWhile deleting `{self.h5fname}`") + def testSimpleSave(self): sig = numpy.array([0, 1, 2]) a0 = numpy.array([2, 3, 4]) From b303c418d886b8dc191297d3199fc95ee396fbeb Mon Sep 17 00:00:00 2001 From: Jerome Kieffer Date: Wed, 3 Dec 2025 11:25:25 +0100 Subject: [PATCH 2/8] Update src/silx/conftest.py Co-authored-by: Thomas VINCENT --- src/silx/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/silx/conftest.py b/src/silx/conftest.py index 7be088750e..c51e1ebcc2 100644 --- a/src/silx/conftest.py +++ b/src/silx/conftest.py @@ -84,7 +84,7 @@ def pytest_configure(config): ) try: import pyopencl -except: +except Exception: pass else: if "RepeatedKernelRetrieval" in dir(pyopencl): From b94f2eb58ce3b15695f542be0d73d1381cb3545a Mon Sep 17 00:00:00 2001 From: Jerome Kieffer Date: Wed, 3 Dec 2025 11:35:47 +0100 Subject: [PATCH 3/8] reformat code --- src/silx/conftest.py | 4 +++- src/silx/io/test/test_nxdata.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/silx/conftest.py b/src/silx/conftest.py index c51e1ebcc2..f1fbe472d7 100644 --- a/src/silx/conftest.py +++ b/src/silx/conftest.py @@ -88,7 +88,9 @@ def pytest_configure(config): pass else: if "RepeatedKernelRetrieval" in dir(pyopencl): - _FILTERWARNINGS = _FILTERWARNINGS + ("ignore::pyopencl.RepeatedKernelRetrieval",) + _FILTERWARNINGS = _FILTERWARNINGS + ( + "ignore::pyopencl.RepeatedKernelRetrieval", + ) def pytest_collection_modifyitems(items): diff --git a/src/silx/io/test/test_nxdata.py b/src/silx/io/test/test_nxdata.py index e7e77a1897..bc7d19f217 100644 --- a/src/silx/io/test/test_nxdata.py +++ b/src/silx/io/test/test_nxdata.py @@ -495,7 +495,7 @@ def tearDown(self): try: os.unlink(self.h5fname) except Exception as err: - print(f"{type(err).__name__}: {err}\nWhile deleting `{self.h5fname}`") + print(f"{type(err).__name__}: {err}\nWhile deleting `{self.h5fname}`") def testSimpleSave(self): sig = numpy.array([0, 1, 2]) From 56a16f5ac969606ea9257da7e6748026de9d63c3 Mon Sep 17 00:00:00 2001 From: Jerome Kieffer Date: Mon, 8 Dec 2025 08:54:41 +0100 Subject: [PATCH 4/8] Check pyopencl version before filtering warnings --- src/silx/conftest.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/silx/conftest.py b/src/silx/conftest.py index f1fbe472d7..ca1173e110 100644 --- a/src/silx/conftest.py +++ b/src/silx/conftest.py @@ -87,7 +87,8 @@ def pytest_configure(config): except Exception: pass else: - if "RepeatedKernelRetrieval" in dir(pyopencl): + pyopen_version = tuple(int(i) for i in pyopencl.__version__.split(".")[:2]) + if pyopen_version >= (2025, 2): _FILTERWARNINGS = _FILTERWARNINGS + ( "ignore::pyopencl.RepeatedKernelRetrieval", ) From afdef395d150e0052ec6c484793ea472ef9b8f66 Mon Sep 17 00:00:00 2001 From: Jerome Kieffer Date: Mon, 8 Dec 2025 17:38:02 +0100 Subject: [PATCH 5/8] Explicit caching of kernels --- src/silx/opencl/processing.py | 46 +++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/src/silx/opencl/processing.py b/src/silx/opencl/processing.py index 0ace8653f4..b4ff6ed4a0 100644 --- a/src/silx/opencl/processing.py +++ b/src/silx/opencl/processing.py @@ -3,7 +3,7 @@ # Project: S I L X project # https://github.com/silx-kit/silx # -# Copyright (C) 2012-2023 European Synchrotron Radiation Facility, Grenoble, France +# Copyright (C) 2012-2025 European Synchrotron Radiation Facility, Grenoble, France # # Principal author: Jérôme Kieffer (Jerome.Kieffer@ESRF.eu) # @@ -37,7 +37,7 @@ __contact__ = "Jerome.Kieffer@ESRF.eu" __license__ = "MIT" __copyright__ = "European Synchrotron Radiation Facility, Grenoble, France" -__date__ = "20/11/2024" +__date__ = "08/12/2025" __status__ = "stable" import os @@ -67,7 +67,10 @@ class KernelContainer: - """Those object holds a copy of all kernels accessible as attributes""" + """Those object holds a copy of all kernels accessible as attributes + + Allows a work around for this issue: https://github.com/inducer/pyopencl/issues/830 + """ def __init__(self, program): """Constructor of the class @@ -75,35 +78,52 @@ def __init__(self, program): :param program: the OpenCL program as generated by PyOpenCL """ self._program = program + self._kernels = {} for kernel in program.all_kernels(): - self.__setattr__(kernel.function_name, kernel) + self._kernels[kernel.function_name] = kernel + + def __repr__(self): + return ( + self.__class__.__name__ + + " with kernels: " + + ", ".join(self._kernels.keys()) + + "." + ) + + def __getattr__(self, name: str): + """Retrieve a kernel, if available + + :param name: name of the kernel + :return: the kernel (not a copy) + """ + if name in self._kernels: + return self._kernels[name] + raise AttributeError(f"`{self.__class__.__name__}` has no attribute `{name}`") def get_kernels(self): "return the dictionary with all kernels" - return dict( - item for item in self.__dict__.items() if not item[0].startswith("_") - ) + return self._kernels - def get_kernel(self, name): + def get_kernel(self, name: str): "get a kernel from its name" logger.debug("KernelContainer.get_kernel(%s)", name) - return self.__dict__.get(name) + return self._kernels.get(name) - def max_workgroup_size(self, kernel_name): + def max_workgroup_size(self, kernel_name: str) -> int: "Retrieve the compile time WORK_GROUP_SIZE for a given kernel" if isinstance(kernel_name, pyopencl.Kernel): kernel = kernel_name else: - kernel = self.get_kernel(kernel_name) + kernel = self._kernels.get(kernel_name) return query_kernel_info(self._program, kernel, "WORK_GROUP_SIZE") - def min_workgroup_size(self, kernel_name): + def min_workgroup_size(self, kernel_name) -> int: "Retrieve the compile time PREFERRED_WORK_GROUP_SIZE_MULTIPLE for a given kernel" if isinstance(kernel_name, pyopencl.Kernel): kernel = kernel_name else: - kernel = self.get_kernel(kernel_name) + kernel = self._kernels.get(kernel_name) return query_kernel_info( self._program, kernel, "PREFERRED_WORK_GROUP_SIZE_MULTIPLE" From 111cfcf23816c59172afdbc96f91ef22909fc942 Mon Sep 17 00:00:00 2001 From: Jerome Kieffer Date: Mon, 8 Dec 2025 17:43:19 +0100 Subject: [PATCH 6/8] The macOS-13 based runner images are being deprecated, consider switching to macOS-15 (macos-15-intel) or macOS 15 arm64 (macos-latest) instead. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 34b381a8d5..f27d086b77 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,7 +55,7 @@ jobs: # python-version: "3.12" # QT_API: PyQt5 # with_opencl: true - - os: macos-13 + - os: macos-latest python-version: "3.13" QT_API: PyQt6 with_opencl: true From 374b0634b001dad88f3189eb3a73ad523f34fb81 Mon Sep 17 00:00:00 2001 From: Jerome Kieffer Date: Mon, 8 Dec 2025 17:47:10 +0100 Subject: [PATCH 7/8] switch back CI to intel processors --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f27d086b77..d0ee1cb131 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,7 +55,7 @@ jobs: # python-version: "3.12" # QT_API: PyQt5 # with_opencl: true - - os: macos-latest + - os: macos-14-intel python-version: "3.13" QT_API: PyQt6 with_opencl: true From 192f27b3ae6b1e61a0f582a93e4bb71a8ed8d2a1 Mon Sep 17 00:00:00 2001 From: Jerome Kieffer Date: Wed, 10 Dec 2025 08:58:34 +0100 Subject: [PATCH 8/8] Update macOS version in CI workflow --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d0ee1cb131..f27d086b77 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,7 +55,7 @@ jobs: # python-version: "3.12" # QT_API: PyQt5 # with_opencl: true - - os: macos-14-intel + - os: macos-latest python-version: "3.13" QT_API: PyQt6 with_opencl: true