kernel-tuner 1.1.2__tar.gz → 1.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/PKG-INFO +22 -20
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/README.md +1 -1
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/__init__.py +1 -1
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/backends/backend.py +21 -5
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/backends/compiler.py +25 -42
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/backends/hip.py +18 -13
- kernel_tuner-1.2.0/kernel_tuner/backends/hypertuner.py +131 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/backends/pycuda.py +4 -1
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/core.py +91 -131
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/file_utils.py +73 -23
- kernel_tuner-1.2.0/kernel_tuner/hyper.py +98 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/integration.py +3 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/interface.py +158 -11
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/runners/sequential.py +1 -1
- kernel_tuner-1.2.0/kernel_tuner/schema/T1/1.0.0/input-schema.json +412 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/searchspace.py +131 -46
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/strategies/bayes_opt.py +85 -42
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/strategies/brute_force.py +3 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/strategies/common.py +29 -15
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/strategies/diff_evo.py +2 -3
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/strategies/firefly_algorithm.py +6 -6
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/strategies/genetic_algorithm.py +2 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/strategies/greedy_ils.py +1 -1
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/strategies/greedy_mls.py +4 -2
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/strategies/hillclimbers.py +4 -2
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/strategies/pso.py +4 -2
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/strategies/random_sample.py +2 -2
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/strategies/simulated_annealing.py +19 -12
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/util.py +236 -227
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/utils/directives.py +142 -17
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/pyproject.toml +54 -54
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/context.py +7 -0
- kernel_tuner-1.2.0/test/convolution.cu +166 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/strategies/test_bayesian_optimization.py +1 -1
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/strategies/test_common.py +8 -3
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/strategies/test_strategies.py +20 -1
- kernel_tuner-1.2.0/test/test_T1_input.json +133 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/test_compiler_functions.py +35 -131
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/test_core.py +2 -1
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/test_file_utils.py +8 -1
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/test_runners.py +11 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/test_searchspace.py +28 -0
- kernel_tuner-1.2.0/test/test_time_budgets.py +79 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/test_util_functions.py +81 -32
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/utils/test_directives.py +48 -2
- kernel_tuner-1.1.2/kernel_tuner/hyper.py +0 -89
- kernel_tuner-1.1.2/test/test_hyper.py +0 -18
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/LICENSE +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/accuracy.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/backends/__init__.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/backends/cupy.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/backends/nvcuda.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/backends/opencl.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/energy/__init__.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/energy/energy.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/kernelbuilder.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/observers/__init__.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/observers/compiler.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/observers/cupy.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/observers/hip.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/observers/ncu.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/observers/nvcuda.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/observers/nvml.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/observers/observer.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/observers/opencl.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/observers/pmt.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/observers/powersensor.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/observers/pycuda.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/observers/register.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/observers/tegra.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/runners/__init__.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/runners/runner.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/runners/simulation.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/schema/T4/1.0.0/metadata-schema.json +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/schema/T4/1.0.0/results-schema.json +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/strategies/__init__.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/strategies/basinhopping.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/strategies/dual_annealing.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/strategies/minimize.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/strategies/mls.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/strategies/ordered_greedy_mls.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/kernel_tuner/utils/__init__.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/__init__.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/strategies/test_genetic_algorithm.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/synthetic_fp32_cache_NVIDIA_RTX_A4000.json +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/test_accuracy.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/test_backend.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/test_cache_file.json +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/test_common.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/test_cuda_functions.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/test_cupy_functions.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/test_energy.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/test_hip_functions.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/test_integration.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/test_kernelbuilder.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/test_nvml_mocked.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/test_observers.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/test_opencl_functions.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/test_pycuda_functions.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/test_pycuda_mocked.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/test_toml_file.py +0 -0
- {kernel_tuner-1.1.2 → kernel_tuner-1.2.0}/test/utils/__init__.py +0 -0
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: kernel_tuner
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.2.0
|
|
4
4
|
Summary: An easy to use CUDA/OpenCL kernel tuner in Python
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
Keywords: auto-tuning,gpu,computing,pycuda,cuda,pyopencl,opencl
|
|
7
7
|
Author: Ben van Werkhoven
|
|
8
8
|
Author-email: b.vanwerkhoven@esciencecenter.nl
|
|
9
|
-
Requires-Python: >=3.
|
|
10
|
-
Classifier: Development Status :: 5 - Production/Stable
|
|
9
|
+
Requires-Python: >=3.10,<4
|
|
11
10
|
Classifier: Environment :: Console
|
|
12
11
|
Classifier: Environment :: GPU
|
|
12
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
13
13
|
Classifier: Intended Audience :: Developers
|
|
14
14
|
Classifier: Intended Audience :: Education
|
|
15
15
|
Classifier: Intended Audience :: Science/Research
|
|
@@ -17,39 +17,41 @@ Classifier: License :: OSI Approved :: Apache Software License
|
|
|
17
17
|
Classifier: Natural Language :: English
|
|
18
18
|
Classifier: Operating System :: MacOS :: MacOS X
|
|
19
19
|
Classifier: Operating System :: POSIX :: Linux
|
|
20
|
-
Classifier:
|
|
21
|
-
Classifier:
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering
|
|
21
|
+
Classifier: Topic :: Software Development
|
|
22
|
+
Classifier: Topic :: System :: Distributed Computing
|
|
22
23
|
Classifier: Programming Language :: Python :: 3.10
|
|
23
24
|
Classifier: Programming Language :: Python :: 3.11
|
|
24
25
|
Classifier: Programming Language :: Python :: 3.12
|
|
25
26
|
Classifier: Programming Language :: Python :: 3.13
|
|
26
|
-
Classifier: Topic :: Scientific/Engineering
|
|
27
|
-
Classifier: Topic :: Software Development
|
|
28
|
-
Classifier: Topic :: System :: Distributed Computing
|
|
29
27
|
Provides-Extra: cuda
|
|
30
28
|
Provides-Extra: cuda-opencl
|
|
31
29
|
Provides-Extra: hip
|
|
32
30
|
Provides-Extra: opencl
|
|
33
31
|
Provides-Extra: tutorial
|
|
34
|
-
Requires-Dist: hip-python
|
|
32
|
+
Requires-Dist: hip-python ; extra == "hip"
|
|
35
33
|
Requires-Dist: jsonschema
|
|
36
|
-
Requires-Dist: jupyter (>=1.0.0
|
|
37
|
-
Requires-Dist: matplotlib (>=3.5.0
|
|
38
|
-
Requires-Dist: numpy (>=2.0.0
|
|
39
|
-
Requires-Dist: nvidia-ml-py (>=12.535.108
|
|
34
|
+
Requires-Dist: jupyter (>=1.0.0) ; extra == "tutorial"
|
|
35
|
+
Requires-Dist: matplotlib (>=3.5.0) ; extra == "tutorial"
|
|
36
|
+
Requires-Dist: numpy (>=2.0.0)
|
|
37
|
+
Requires-Dist: nvidia-ml-py (>=12.535.108) ; extra == "cuda"
|
|
38
|
+
Requires-Dist: nvidia-ml-py (>=12.535.108) ; extra == "tutorial"
|
|
40
39
|
Requires-Dist: packaging
|
|
41
40
|
Requires-Dist: pandas (>=2.0.0)
|
|
42
|
-
Requires-Dist: pycuda (>=2024.1
|
|
43
|
-
Requires-Dist:
|
|
44
|
-
Requires-Dist:
|
|
45
|
-
Requires-Dist:
|
|
41
|
+
Requires-Dist: pycuda (>=2024.1) ; extra == "cuda-opencl"
|
|
42
|
+
Requires-Dist: pycuda (>=2025.1) ; extra == "cuda"
|
|
43
|
+
Requires-Dist: pynvml (>=11.4.1) ; extra == "cuda"
|
|
44
|
+
Requires-Dist: pyopencl ; extra == "cuda-opencl"
|
|
45
|
+
Requires-Dist: pyopencl ; extra == "opencl"
|
|
46
|
+
Requires-Dist: python-constraint2 (>=2.3.1)
|
|
46
47
|
Requires-Dist: scikit-learn (>=1.0.2)
|
|
47
|
-
Requires-Dist: scipy (>=1.
|
|
48
|
+
Requires-Dist: scipy (>=1.14.1)
|
|
48
49
|
Requires-Dist: xmltodict
|
|
49
50
|
Project-URL: Documentation, https://KernelTuner.github.io/kernel_tuner/
|
|
50
51
|
Project-URL: Homepage, https://KernelTuner.github.io/kernel_tuner/
|
|
51
52
|
Project-URL: Repository, https://github.com/KernelTuner/kernel_tuner
|
|
52
|
-
Project-URL:
|
|
53
|
+
Project-URL: changelog, https://github.com/KernelTuner/kernel_tuner/blob/master/CHANGELOG.md
|
|
54
|
+
Project-URL: issues, https://github.com/KernelTuner/kernel_tuner/issues
|
|
53
55
|
Description-Content-Type: text/markdown
|
|
54
56
|
|
|
55
57
|
|
|
@@ -70,7 +72,7 @@ Description-Content-Type: text/markdown
|
|
|
70
72
|
|
|
71
73
|
|
|
72
74
|
Create optimized GPU applications in any mainstream GPU
|
|
73
|
-
programming language (CUDA, HIP, OpenCL, OpenACC).
|
|
75
|
+
programming language (CUDA, HIP, OpenCL, OpenACC, OpenMP).
|
|
74
76
|
|
|
75
77
|
What Kernel Tuner does:
|
|
76
78
|
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
"""This module contains the interface of all kernel_tuner backends"""
|
|
1
|
+
"""This module contains the interface of all kernel_tuner backends."""
|
|
2
2
|
from __future__ import print_function
|
|
3
3
|
|
|
4
4
|
from abc import ABC, abstractmethod
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class Backend(ABC):
|
|
8
|
-
"""Base class for kernel_tuner backends"""
|
|
8
|
+
"""Base class for kernel_tuner backends."""
|
|
9
9
|
|
|
10
10
|
@abstractmethod
|
|
11
11
|
def ready_argument_list(self, arguments):
|
|
12
12
|
"""This method must implement the allocation of the arguments on device memory."""
|
|
13
|
-
|
|
13
|
+
return arguments
|
|
14
14
|
|
|
15
15
|
@abstractmethod
|
|
16
16
|
def compile(self, kernel_instance):
|
|
@@ -57,9 +57,14 @@ class Backend(ABC):
|
|
|
57
57
|
"""This method must implement a host to device copy."""
|
|
58
58
|
pass
|
|
59
59
|
|
|
60
|
+
@abstractmethod
|
|
61
|
+
def refresh_memory(self, device_memory, host_arguments, should_sync):
|
|
62
|
+
"""This method must implement refreshing the device memory with a clean copy."""
|
|
63
|
+
pass
|
|
64
|
+
|
|
60
65
|
|
|
61
66
|
class GPUBackend(Backend):
|
|
62
|
-
"""Base class for GPU backends"""
|
|
67
|
+
"""Base class for GPU backends."""
|
|
63
68
|
|
|
64
69
|
@abstractmethod
|
|
65
70
|
def __init__(self, device, iterations, compiler_options, observers):
|
|
@@ -80,10 +85,21 @@ class GPUBackend(Backend):
|
|
|
80
85
|
"""This method must implement the allocation and copy of texture memory to the GPU."""
|
|
81
86
|
pass
|
|
82
87
|
|
|
88
|
+
def refresh_memory(self, gpu_memory, host_arguments, should_sync):
|
|
89
|
+
"""Refresh the GPU memory with the untouched host arguments."""
|
|
90
|
+
for i, arg in enumerate(host_arguments):
|
|
91
|
+
if should_sync[i]:
|
|
92
|
+
self.memcpy_htod(gpu_memory[i], arg)
|
|
93
|
+
|
|
83
94
|
|
|
84
95
|
class CompilerBackend(Backend):
|
|
85
|
-
"""Base class for compiler backends"""
|
|
96
|
+
"""Base class for compiler backends."""
|
|
86
97
|
|
|
87
98
|
@abstractmethod
|
|
88
99
|
def __init__(self, iterations, compiler_options, compiler):
|
|
89
100
|
pass
|
|
101
|
+
|
|
102
|
+
@abstractmethod
|
|
103
|
+
def cleanup_lib(self):
|
|
104
|
+
"""Unload the previously loaded shared library"""
|
|
105
|
+
pass
|
|
@@ -34,7 +34,7 @@ except ImportError:
|
|
|
34
34
|
try:
|
|
35
35
|
from hip._util.types import DeviceArray
|
|
36
36
|
except ImportError:
|
|
37
|
-
Pointer = Exception
|
|
37
|
+
Pointer = Exception # using Exception here as a type that will never be among kernel arguments
|
|
38
38
|
DeviceArray = Exception
|
|
39
39
|
|
|
40
40
|
|
|
@@ -93,8 +93,12 @@ class CompilerFunctions(CompilerBackend):
|
|
|
93
93
|
:param iterations: Number of iterations used while benchmarking a kernel, 7 by default.
|
|
94
94
|
:type iterations: int
|
|
95
95
|
"""
|
|
96
|
+
# allocations contains a clean copy of the memory
|
|
97
|
+
self.allocations = []
|
|
96
98
|
self.observers = observers or []
|
|
97
99
|
self.observers.append(CompilerRuntimeObserver(self))
|
|
100
|
+
for obs in self.observers:
|
|
101
|
+
obs.register_device(self)
|
|
98
102
|
|
|
99
103
|
self.iterations = iterations
|
|
100
104
|
self.max_threads = 1024
|
|
@@ -104,7 +108,6 @@ class CompilerFunctions(CompilerBackend):
|
|
|
104
108
|
self.lib = None
|
|
105
109
|
self.using_openmp = False
|
|
106
110
|
self.using_openacc = False
|
|
107
|
-
self.observers = [CompilerRuntimeObserver(self)]
|
|
108
111
|
self.last_result = None
|
|
109
112
|
|
|
110
113
|
if self.compiler == "g++":
|
|
@@ -157,30 +160,24 @@ class CompilerFunctions(CompilerBackend):
|
|
|
157
160
|
|
|
158
161
|
for i, arg in enumerate(arguments):
|
|
159
162
|
if not (isinstance(arg, (np.ndarray, np.number, DeviceArray)) or is_cupy_array(arg)):
|
|
160
|
-
raise TypeError(
|
|
163
|
+
raise TypeError(
|
|
164
|
+
f"Argument is not numpy or cupy ndarray or numpy scalar or HIP Python DeviceArray but a {type(arg)}"
|
|
165
|
+
)
|
|
161
166
|
dtype_str = arg.typestr if isinstance(arg, DeviceArray) else str(arg.dtype)
|
|
162
167
|
if isinstance(arg, np.ndarray):
|
|
163
168
|
if dtype_str in dtype_map.keys():
|
|
164
|
-
# In numpy <= 1.15, ndarray.ctypes.data_as does not itself keep a reference
|
|
165
|
-
# to its underlying array, so we need to store a reference to arg.copy()
|
|
166
|
-
# in the Argument object manually to avoid it being deleted.
|
|
167
|
-
# (This changed in numpy > 1.15.)
|
|
168
|
-
# data_ctypes = data.ctypes.data_as(C.POINTER(dtype_map[dtype_str]))
|
|
169
169
|
data_ctypes = arg.ctypes.data_as(C.POINTER(dtype_map[dtype_str]))
|
|
170
|
-
numpy_arg = arg
|
|
171
170
|
else:
|
|
172
171
|
raise TypeError("unknown dtype for ndarray")
|
|
173
172
|
elif isinstance(arg, np.generic):
|
|
174
173
|
data_ctypes = dtype_map[dtype_str](arg)
|
|
175
|
-
numpy_arg = arg
|
|
176
174
|
elif is_cupy_array(arg):
|
|
177
175
|
data_ctypes = C.c_void_p(arg.data.ptr)
|
|
178
|
-
numpy_arg = arg
|
|
179
176
|
elif isinstance(arg, DeviceArray):
|
|
180
177
|
data_ctypes = arg.as_c_void_p()
|
|
181
|
-
numpy_arg = None
|
|
182
178
|
|
|
183
|
-
ctype_args[i] = Argument(numpy=
|
|
179
|
+
ctype_args[i] = Argument(numpy=arg, ctypes=data_ctypes)
|
|
180
|
+
self.allocations.append(Argument(numpy=arg.copy(), ctypes=data_ctypes))
|
|
184
181
|
return ctype_args
|
|
185
182
|
|
|
186
183
|
def compile(self, kernel_instance):
|
|
@@ -204,16 +201,13 @@ class CompilerFunctions(CompilerBackend):
|
|
|
204
201
|
compiler_options = ["-fPIC"]
|
|
205
202
|
|
|
206
203
|
# detect openmp
|
|
207
|
-
if "#
|
|
204
|
+
if "#pragma omp" in kernel_string or "!$omp" in kernel_string:
|
|
208
205
|
logging.debug("set using_openmp to true")
|
|
209
206
|
self.using_openmp = True
|
|
210
|
-
if self.compiler in ["nvc", "nvc++", "nvfortran"]:
|
|
211
|
-
compiler_options.append("-mp")
|
|
212
|
-
else:
|
|
213
|
-
compiler_options.append("-fopenmp")
|
|
214
207
|
|
|
215
208
|
# detect openacc
|
|
216
209
|
if "#pragma acc" in kernel_string or "!$acc" in kernel_string:
|
|
210
|
+
logging.debug("set using_openacc to true")
|
|
217
211
|
self.using_openacc = True
|
|
218
212
|
|
|
219
213
|
# if filename is known, use that one
|
|
@@ -288,7 +282,7 @@ class CompilerFunctions(CompilerBackend):
|
|
|
288
282
|
stdout=subprocess.PIPE,
|
|
289
283
|
stderr=subprocess.PIPE,
|
|
290
284
|
text=True,
|
|
291
|
-
check=True
|
|
285
|
+
check=True,
|
|
292
286
|
)
|
|
293
287
|
|
|
294
288
|
subprocess.run(
|
|
@@ -299,7 +293,7 @@ class CompilerFunctions(CompilerBackend):
|
|
|
299
293
|
stdout=subprocess.PIPE,
|
|
300
294
|
stderr=subprocess.PIPE,
|
|
301
295
|
text=True,
|
|
302
|
-
check=True
|
|
296
|
+
check=True,
|
|
303
297
|
)
|
|
304
298
|
|
|
305
299
|
self.lib = np.ctypeslib.load_library(filename, ".")
|
|
@@ -390,7 +384,8 @@ class CompilerFunctions(CompilerBackend):
|
|
|
390
384
|
C.memset(allocation.ctypes, value, size)
|
|
391
385
|
|
|
392
386
|
def memcpy_dtoh(self, dest, src):
|
|
393
|
-
"""
|
|
387
|
+
"""This method implements the semantic of a device to host copy for the Compiler backend.
|
|
388
|
+
There is no actual copy from device to host happening, but host to host.
|
|
394
389
|
|
|
395
390
|
:param dest: A numpy or cupy array to store the data
|
|
396
391
|
:type dest: np.ndarray or cupy.ndarray
|
|
@@ -404,6 +399,7 @@ class CompilerFunctions(CompilerBackend):
|
|
|
404
399
|
# This is because DeviceArray manages its own memory and donesn't need
|
|
405
400
|
# explicit copies like numpy arrays do
|
|
406
401
|
return
|
|
402
|
+
# there is no real copy from device to host, but host to host
|
|
407
403
|
if isinstance(dest, np.ndarray) and is_cupy_array(src.numpy):
|
|
408
404
|
# Implicit conversion to a NumPy array is not allowed.
|
|
409
405
|
value = src.numpy.get()
|
|
@@ -413,33 +409,20 @@ class CompilerFunctions(CompilerBackend):
|
|
|
413
409
|
dest[:] = xp.asarray(value)
|
|
414
410
|
|
|
415
411
|
def memcpy_htod(self, dest, src):
|
|
416
|
-
"""
|
|
417
|
-
|
|
418
|
-
:param dest: An Argument for some memory allocation
|
|
419
|
-
:type dest: Argument
|
|
412
|
+
"""There is no memcpy_htod implemented for the compiler backend."""
|
|
413
|
+
pass
|
|
420
414
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
# Skip memory copies for HIP Python DeviceArray
|
|
427
|
-
# This is because DeviceArray manages its own memory and donesn't need
|
|
428
|
-
# explicit copies like numpy arrays do
|
|
429
|
-
return
|
|
430
|
-
if isinstance(dest.numpy, np.ndarray) and is_cupy_array(src):
|
|
431
|
-
# Implicit conversion to a NumPy array is not allowed.
|
|
432
|
-
value = src.get()
|
|
433
|
-
else:
|
|
434
|
-
value = src
|
|
435
|
-
xp = get_array_module(dest.numpy)
|
|
436
|
-
dest.numpy[:] = xp.asarray(value)
|
|
415
|
+
def refresh_memory(self, _, arguments, should_sync):
|
|
416
|
+
"""Copy the preserved content of the output memory to used arrays."""
|
|
417
|
+
for i, arg in enumerate(arguments):
|
|
418
|
+
if should_sync[i]:
|
|
419
|
+
self.memcpy_dtoh(arg, self.allocations[i])
|
|
437
420
|
|
|
438
421
|
def cleanup_lib(self):
|
|
439
422
|
"""unload the previously loaded shared library"""
|
|
440
423
|
if self.lib is None:
|
|
441
424
|
return
|
|
442
|
-
|
|
425
|
+
|
|
443
426
|
if not self.using_openmp and not self.using_openacc:
|
|
444
427
|
# this if statement is necessary because shared libraries that use
|
|
445
428
|
# OpenMP will core dump when unloaded, this is a well-known issue with OpenMP
|
|
@@ -19,7 +19,6 @@ dtype_map = {
|
|
|
19
19
|
"bool": ctypes.c_bool,
|
|
20
20
|
"int8": ctypes.c_int8,
|
|
21
21
|
"int16": ctypes.c_int16,
|
|
22
|
-
"float16": ctypes.c_int16,
|
|
23
22
|
"int32": ctypes.c_int32,
|
|
24
23
|
"int64": ctypes.c_int64,
|
|
25
24
|
"uint8": ctypes.c_uint8,
|
|
@@ -40,7 +39,9 @@ def hip_check(call_result):
|
|
|
40
39
|
if len(result) == 1:
|
|
41
40
|
result = result[0]
|
|
42
41
|
if isinstance(err, hip.hipError_t) and err != hip.hipError_t.hipSuccess:
|
|
43
|
-
|
|
42
|
+
_, error_name = hip.hipGetErrorName(err)
|
|
43
|
+
_, error_str = hip.hipGetErrorString(err)
|
|
44
|
+
raise RuntimeError(f"{error_name}: {error_str}")
|
|
44
45
|
return result
|
|
45
46
|
|
|
46
47
|
|
|
@@ -120,25 +121,29 @@ class HipFunctions(GPUBackend):
|
|
|
120
121
|
|
|
121
122
|
# Handle numpy arrays
|
|
122
123
|
if isinstance(arg, np.ndarray):
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
device_ptr = hip_check(hip.hipMalloc(arg.nbytes))
|
|
124
|
+
# Allocate device memory
|
|
125
|
+
device_ptr = hip_check(hip.hipMalloc(arg.nbytes))
|
|
126
126
|
|
|
127
|
-
|
|
128
|
-
|
|
127
|
+
# Copy data to device using hipMemcpy
|
|
128
|
+
hip_check(hip.hipMemcpy(device_ptr, arg, arg.nbytes, hip.hipMemcpyKind.hipMemcpyHostToDevice))
|
|
129
129
|
|
|
130
|
-
|
|
131
|
-
else:
|
|
132
|
-
raise TypeError(f"Unknown dtype {dtype_str} for ndarray")
|
|
130
|
+
prepared_args.append(device_ptr)
|
|
133
131
|
|
|
134
132
|
# Handle numpy scalar types
|
|
135
133
|
elif isinstance(arg, np.generic):
|
|
136
134
|
# Convert numpy scalar to corresponding ctypes
|
|
137
|
-
|
|
138
|
-
|
|
135
|
+
if dtype_str in dtype_map:
|
|
136
|
+
ctype_arg = dtype_map[dtype_str](arg)
|
|
137
|
+
prepared_args.append(ctype_arg)
|
|
138
|
+
# 16-bit float is not supported, view it as uint16
|
|
139
|
+
elif dtype_str in ("float16", "bfloat16"):
|
|
140
|
+
ctype_arg = ctypes.c_uint16(arg.view(np.uint16))
|
|
141
|
+
prepared_args.append(ctype_arg)
|
|
142
|
+
else:
|
|
143
|
+
raise ValueError(f"Invalid argument type {dtype_str}: {arg}")
|
|
139
144
|
|
|
140
145
|
else:
|
|
141
|
-
raise ValueError(f"Invalid argument type {type(arg)}
|
|
146
|
+
raise ValueError(f"Invalid argument type {type(arg)}: {arg}")
|
|
142
147
|
|
|
143
148
|
return prepared_args
|
|
144
149
|
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"""This module contains a 'device' for hyperparameter tuning using the autotuning methodology."""
|
|
2
|
+
|
|
3
|
+
import platform
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from numpy import mean
|
|
7
|
+
|
|
8
|
+
from kernel_tuner.backends.backend import Backend
|
|
9
|
+
from kernel_tuner.observers.observer import BenchmarkObserver
|
|
10
|
+
|
|
11
|
+
try:
|
|
12
|
+
methodology_available = True
|
|
13
|
+
from autotuning_methodology.experiments import generate_experiment_file
|
|
14
|
+
from autotuning_methodology.report_experiments import get_strategy_scores
|
|
15
|
+
except ImportError:
|
|
16
|
+
methodology_available = False
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ScoreObserver(BenchmarkObserver):
|
|
20
|
+
def __init__(self, dev):
|
|
21
|
+
self.dev = dev
|
|
22
|
+
self.scores = []
|
|
23
|
+
|
|
24
|
+
def after_finish(self):
|
|
25
|
+
self.scores.append(self.dev.last_score)
|
|
26
|
+
|
|
27
|
+
def get_results(self):
|
|
28
|
+
results = {'score': mean(self.scores), 'scores': self.scores.copy()}
|
|
29
|
+
self.scores = []
|
|
30
|
+
return results
|
|
31
|
+
|
|
32
|
+
class HypertunerFunctions(Backend):
|
|
33
|
+
"""Class for executing hyperparameter tuning."""
|
|
34
|
+
units = {}
|
|
35
|
+
|
|
36
|
+
def __init__(self, iterations):
|
|
37
|
+
self.iterations = iterations
|
|
38
|
+
self.observers = [ScoreObserver(self)]
|
|
39
|
+
self.name = platform.processor()
|
|
40
|
+
self.max_threads = 1024
|
|
41
|
+
self.last_score = None
|
|
42
|
+
|
|
43
|
+
# set the environment options
|
|
44
|
+
env = dict()
|
|
45
|
+
env["iterations"] = self.iterations
|
|
46
|
+
self.env = env
|
|
47
|
+
|
|
48
|
+
# check for the methodology package
|
|
49
|
+
if methodology_available is not True:
|
|
50
|
+
raise ImportError("Unable to import the autotuning methodology, run `pip install autotuning_methodology`.")
|
|
51
|
+
|
|
52
|
+
def ready_argument_list(self, arguments):
|
|
53
|
+
arglist = super().ready_argument_list(arguments)
|
|
54
|
+
if arglist is None:
|
|
55
|
+
arglist = []
|
|
56
|
+
return arglist
|
|
57
|
+
|
|
58
|
+
def compile(self, kernel_instance):
|
|
59
|
+
super().compile(kernel_instance)
|
|
60
|
+
path = Path(__file__).parent.parent.parent / "hyperparamtuning"
|
|
61
|
+
path.mkdir(exist_ok=True)
|
|
62
|
+
|
|
63
|
+
# TODO get applications & GPUs args from benchmark
|
|
64
|
+
gpus = ["RTX_3090", "RTX_2080_Ti"]
|
|
65
|
+
applications = None
|
|
66
|
+
# applications = [
|
|
67
|
+
# {
|
|
68
|
+
# "name": "convolution",
|
|
69
|
+
# "folder": "./cached_data_used/kernels",
|
|
70
|
+
# "input_file": "convolution.json"
|
|
71
|
+
# },
|
|
72
|
+
# {
|
|
73
|
+
# "name": "pnpoly",
|
|
74
|
+
# "folder": "./cached_data_used/kernels",
|
|
75
|
+
# "input_file": "pnpoly.json"
|
|
76
|
+
# }
|
|
77
|
+
# ]
|
|
78
|
+
|
|
79
|
+
# strategy settings
|
|
80
|
+
strategy: str = kernel_instance.arguments[0]
|
|
81
|
+
hyperparams = [{'name': k, 'value': v} for k, v in kernel_instance.params.items()]
|
|
82
|
+
hyperparams_string = "_".join(f"{k}={str(v)}" for k, v in kernel_instance.params.items())
|
|
83
|
+
searchspace_strategies = [{
|
|
84
|
+
"autotuner": "KernelTuner",
|
|
85
|
+
"name": f"{strategy.lower()}_{hyperparams_string}",
|
|
86
|
+
"display_name": strategy.replace('_', ' ').capitalize(),
|
|
87
|
+
"search_method": strategy.lower(),
|
|
88
|
+
'search_method_hyperparameters': hyperparams
|
|
89
|
+
}]
|
|
90
|
+
|
|
91
|
+
# any additional settings
|
|
92
|
+
override = {
|
|
93
|
+
"experimental_groups_defaults": {
|
|
94
|
+
"samples": self.iterations
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
name = kernel_instance.name if len(kernel_instance.name) > 0 else kernel_instance.kernel_source.kernel_name
|
|
99
|
+
experiments_filepath = generate_experiment_file(name, path, searchspace_strategies, applications, gpus,
|
|
100
|
+
override=override, overwrite_existing_file=True)
|
|
101
|
+
return str(experiments_filepath)
|
|
102
|
+
|
|
103
|
+
def start_event(self):
|
|
104
|
+
return super().start_event()
|
|
105
|
+
|
|
106
|
+
def stop_event(self):
|
|
107
|
+
return super().stop_event()
|
|
108
|
+
|
|
109
|
+
def kernel_finished(self):
|
|
110
|
+
super().kernel_finished()
|
|
111
|
+
return True
|
|
112
|
+
|
|
113
|
+
def synchronize(self):
|
|
114
|
+
return super().synchronize()
|
|
115
|
+
|
|
116
|
+
def run_kernel(self, func, gpu_args=None, threads=None, grid=None, stream=None):
|
|
117
|
+
# generate the experiments file
|
|
118
|
+
experiments_filepath = Path(func)
|
|
119
|
+
|
|
120
|
+
# run the methodology to get a fitness score for this configuration
|
|
121
|
+
scores = get_strategy_scores(str(experiments_filepath))
|
|
122
|
+
self.last_score = scores[list(scores.keys())[0]]['score']
|
|
123
|
+
|
|
124
|
+
def memset(self, allocation, value, size):
|
|
125
|
+
return super().memset(allocation, value, size)
|
|
126
|
+
|
|
127
|
+
def memcpy_dtoh(self, dest, src):
|
|
128
|
+
return super().memcpy_dtoh(dest, src)
|
|
129
|
+
|
|
130
|
+
def memcpy_htod(self, dest, src):
|
|
131
|
+
return super().memcpy_htod(dest, src)
|
|
@@ -106,7 +106,7 @@ class PyCudaFunctions(GPUBackend):
|
|
|
106
106
|
)
|
|
107
107
|
if cc == "00":
|
|
108
108
|
cc = self.context.get_device().compute_capability()
|
|
109
|
-
self.cc = str(cc
|
|
109
|
+
self.cc = str(cc)
|
|
110
110
|
self.iterations = iterations
|
|
111
111
|
self.current_module = None
|
|
112
112
|
self.func = None
|
|
@@ -180,6 +180,9 @@ class PyCudaFunctions(GPUBackend):
|
|
|
180
180
|
# pycuda does not support bool, convert to uint8 instead
|
|
181
181
|
elif isinstance(arg, np.bool_):
|
|
182
182
|
gpu_args.append(arg.astype(np.uint8))
|
|
183
|
+
# pycuda does not support 16-bit formats, view them as uint16
|
|
184
|
+
elif isinstance(arg, np.generic) and str(arg.dtype) in ("float16", "bfloat16"):
|
|
185
|
+
gpu_args.append(arg.view(np.uint16))
|
|
183
186
|
# if not an array, just pass argument along
|
|
184
187
|
else:
|
|
185
188
|
gpu_args.append(arg)
|