kernel-tuner 1.3.3__tar.gz → 1.4.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.3.3 → kernel_tuner-1.4.0}/PKG-INFO +4 -3
- kernel_tuner-1.4.0/kernel_tuner/__init__.py +22 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/backends/cupy.py +13 -7
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/backends/hip/hip.py +47 -4
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/backends/nvcuda.py +133 -25
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/backends/pycuda.py +7 -6
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/core.py +116 -71
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/file_utils.py +40 -17
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/integration.py +1 -29
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/interface.py +204 -67
- kernel_tuner-1.4.0/kernel_tuner/observers/amd.py +401 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/observers/nvml.py +91 -24
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/observers/pmt.py +10 -5
- kernel_tuner-1.4.0/kernel_tuner/runners/parallel.py +405 -0
- kernel_tuner-1.4.0/kernel_tuner/runners/runner.py +38 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/runners/sequential.py +69 -39
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/runners/simulation.py +64 -52
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/searchspace.py +21 -20
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/strategies/bayes_opt.py +27 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/strategies/common.py +114 -68
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/strategies/diff_evo.py +4 -4
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/strategies/firefly_algorithm.py +7 -6
- kernel_tuner-1.4.0/kernel_tuner/strategies/gen_adaptive_tabu_greywolf.py +239 -0
- kernel_tuner-1.4.0/kernel_tuner/strategies/gen_hybrid_vndx.py +236 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/strategies/genetic_algorithm.py +11 -14
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/strategies/greedy_ils.py +2 -3
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/strategies/greedy_mls.py +2 -3
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/strategies/hillclimbers.py +18 -16
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/strategies/pso.py +19 -14
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/strategies/pyatf_strategies.py +1 -1
- kernel_tuner-1.4.0/kernel_tuner/strategies/pymoo_minimize.py +256 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/strategies/random_sample.py +5 -8
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/strategies/simulated_annealing.py +1 -1
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/util.py +302 -74
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/utils/nvcuda.py +25 -4
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/pyproject.toml +4 -3
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/context.py +9 -1
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/strategies/test_bayesian_optimization.py +2 -0
- kernel_tuner-1.4.0/test/strategies/test_cache_time_energy.json +48 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/strategies/test_common.py +10 -10
- kernel_tuner-1.4.0/test/strategies/test_pymoo_strategies.py +36 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/strategies/test_strategies.py +5 -4
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/test_cache_file.json +2 -1
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/test_cache_file_T1_input.json +2 -2
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/test_common.py +14 -6
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/test_core.py +36 -69
- kernel_tuner-1.4.0/test/test_cuda_functions.py +154 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/test_energy.py +2 -2
- kernel_tuner-1.4.0/test/test_lazy_imports.py +47 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/test_observers.py +21 -3
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/test_runners.py +18 -11
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/test_util_functions.py +114 -9
- kernel_tuner-1.3.3/kernel_tuner/__init__.py +0 -6
- kernel_tuner-1.3.3/kernel_tuner/runners/runner.py +0 -22
- kernel_tuner-1.3.3/test/test_cuda_functions.py +0 -60
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/LICENSE +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/README.md +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/accuracy.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/backends/__init__.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/backends/backend.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/backends/compiler.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/backends/hip/__init__.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/backends/hip/util.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/backends/hypertuner.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/backends/opencl.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/energy/__init__.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/energy/energy.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/hyper.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/kernelbuilder.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/observers/__init__.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/observers/compiler.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/observers/cupy.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/observers/hip.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/observers/ncu.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/observers/nvcuda.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/observers/observer.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/observers/opencl.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/observers/powersensor.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/observers/pycuda.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/observers/register.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/observers/tegra.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/runners/__init__.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/schema/T1/1.0.0/input-schema.json +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/schema/T4/1.0.0/metadata-schema.json +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/schema/T4/1.0.0/results-schema.json +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/strategies/__init__.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/strategies/basinhopping.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/strategies/brute_force.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/strategies/dual_annealing.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/strategies/minimize.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/strategies/mls.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/strategies/ordered_greedy_mls.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/strategies/skopt.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/strategies/wrapper.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/utils/__init__.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/kernel_tuner/utils/directives.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/__init__.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/conftest.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/convolution.cu +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/strategies/__init__.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/strategies/test_cache_file.json +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/strategies/test_diff_evo.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/strategies/test_genetic_algorithm.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/synthetic_fp32_cache_NVIDIA_RTX_A4000.json +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/test_T1_input.json +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/test_accuracy.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/test_backend.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/test_compiler_functions.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/test_cupy_functions.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/test_custom_optimizer.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/test_file_utils.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/test_hip_functions.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/test_hyper.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/test_integration.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/test_kernelbuilder.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/test_nvml_mocked.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/test_opencl_functions.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/test_pycuda_functions.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/test_pycuda_mocked.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/test_searchspace.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/test_time_budgets.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/test_toml_file.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/utils/__init__.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/utils/nvcuda.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/utils/test_directives.py +0 -0
- {kernel_tuner-1.3.3 → kernel_tuner-1.4.0}/test/vector_add.cu +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: kernel_tuner
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.0
|
|
4
4
|
Summary: An easy to use CUDA/OpenCL kernel tuner in Python
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
License-File: LICENSE
|
|
@@ -30,6 +30,8 @@ Provides-Extra: cuda-opencl
|
|
|
30
30
|
Provides-Extra: hip
|
|
31
31
|
Provides-Extra: opencl
|
|
32
32
|
Provides-Extra: tutorial
|
|
33
|
+
Requires-Dist: cuda-python (>=12.6.0) ; extra == "cuda"
|
|
34
|
+
Requires-Dist: cuda-python (>=12.6.0) ; extra == "cuda-opencl"
|
|
33
35
|
Requires-Dist: hip-python ; extra == "hip"
|
|
34
36
|
Requires-Dist: jsonschema
|
|
35
37
|
Requires-Dist: jupyter (>=1.0.0) ; extra == "tutorial"
|
|
@@ -39,8 +41,7 @@ Requires-Dist: nvidia-ml-py (>=12.535.108) ; extra == "cuda"
|
|
|
39
41
|
Requires-Dist: nvidia-ml-py (>=12.535.108) ; extra == "tutorial"
|
|
40
42
|
Requires-Dist: packaging
|
|
41
43
|
Requires-Dist: pandas (>=2.0.0)
|
|
42
|
-
Requires-Dist:
|
|
43
|
-
Requires-Dist: pycuda (>=2025.1) ; extra == "cuda"
|
|
44
|
+
Requires-Dist: pymoo (>=0.6.1.6)
|
|
44
45
|
Requires-Dist: pynvml (>=11.4.1) ; extra == "cuda"
|
|
45
46
|
Requires-Dist: pyopencl ; extra == "cuda-opencl"
|
|
46
47
|
Requires-Dist: pyopencl ; extra == "opencl"
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from importlib.metadata import version
|
|
2
|
+
|
|
3
|
+
from kernel_tuner.interface import run_kernel, tune_kernel, tune_kernel_T1, tune_cache
|
|
4
|
+
|
|
5
|
+
__version__ = version(__package__)
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"create_device_targets",
|
|
9
|
+
"run_kernel",
|
|
10
|
+
"store_results",
|
|
11
|
+
"tune_kernel",
|
|
12
|
+
"tune_cache",
|
|
13
|
+
"tune_kernel_T1",
|
|
14
|
+
"__version__",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def __getattr__(name):
|
|
19
|
+
if name in ("store_results", "create_device_targets"):
|
|
20
|
+
from kernel_tuner import integration
|
|
21
|
+
return getattr(integration, name)
|
|
22
|
+
raise AttributeError(f"module 'kernel_tuner' has no attribute {name!r}")
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
from __future__ import print_function
|
|
3
3
|
|
|
4
4
|
import numpy as np
|
|
5
|
+
import uuid
|
|
5
6
|
|
|
6
7
|
from kernel_tuner.backends.backend import GPUBackend
|
|
7
8
|
from kernel_tuner.observers.cupy import CupyRuntimeObserver
|
|
@@ -61,28 +62,33 @@ class CupyFunctions(GPUBackend):
|
|
|
61
62
|
# default dynamically allocated shared memory size, can be overwritten using smem_args
|
|
62
63
|
self.smem_size = 0
|
|
63
64
|
|
|
64
|
-
# setup observers
|
|
65
|
-
self.observers = observers or []
|
|
66
|
-
self.observers.append(CupyRuntimeObserver(self))
|
|
67
|
-
for obs in self.observers:
|
|
68
|
-
obs.register_device(self)
|
|
69
|
-
|
|
70
65
|
# collect environment information
|
|
71
66
|
env = dict()
|
|
72
67
|
cupy_info = str(get_runtime_info()).split("\n")[:-1]
|
|
73
68
|
info_dict = {
|
|
74
|
-
s.split(":")[0].strip(): s.split(":")[1].strip() for s in cupy_info
|
|
69
|
+
s.split(":", 1)[0].strip(): s.split(":", 1)[1].strip() for s in cupy_info
|
|
75
70
|
}
|
|
76
71
|
env["device_name"] = info_dict[f"Device {device} Name"]
|
|
72
|
+
env["pci_bus_id"] = info_dict[f"Device {device} PCI Bus ID"]
|
|
77
73
|
|
|
78
74
|
env["cuda_version"] = cp.cuda.runtime.driverGetVersion()
|
|
79
75
|
env["compute_capability"] = self.cc
|
|
80
76
|
env["iterations"] = self.iterations
|
|
81
77
|
env["compiler_options"] = compiler_options
|
|
82
78
|
env["device_properties"] = self.devprops
|
|
79
|
+
|
|
80
|
+
props = cp.cuda.runtime.getDeviceProperties(device)
|
|
81
|
+
env["uuid"] = str(uuid.UUID(bytes=props["uuid"]))
|
|
82
|
+
|
|
83
83
|
self.env = env
|
|
84
84
|
self.name = env["device_name"]
|
|
85
85
|
|
|
86
|
+
# setup observers
|
|
87
|
+
self.observers = observers or []
|
|
88
|
+
self.observers.append(CupyRuntimeObserver(self))
|
|
89
|
+
for obs in self.observers:
|
|
90
|
+
obs.register_device(self)
|
|
91
|
+
|
|
86
92
|
def ready_argument_list(self, arguments):
|
|
87
93
|
"""Ready argument list to be passed to the kernel, allocates gpu mem.
|
|
88
94
|
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
import ctypes
|
|
4
4
|
import ctypes.util
|
|
5
5
|
import logging
|
|
6
|
+
import json
|
|
7
|
+
import uuid
|
|
6
8
|
|
|
7
9
|
import numpy as np
|
|
8
10
|
|
|
@@ -32,8 +34,35 @@ dtype_map = {
|
|
|
32
34
|
|
|
33
35
|
hipSuccess = 0
|
|
34
36
|
|
|
37
|
+
|
|
38
|
+
def extract_safe_properties(props):
|
|
39
|
+
"""Extract those properties that are 'safe' (i.e, json serializable)"""
|
|
40
|
+
result = dict()
|
|
41
|
+
|
|
42
|
+
for key in props.PROPERTIES():
|
|
43
|
+
try:
|
|
44
|
+
value = getattr(props, key)
|
|
45
|
+
if isinstance(value, (str, int, float)):
|
|
46
|
+
# These are safe
|
|
47
|
+
result[key] = value
|
|
48
|
+
elif isinstance(value, (bytes, bytearray)):
|
|
49
|
+
# bytes/bytearray is typically a string
|
|
50
|
+
result[key] = value.decode("utf-8").rstrip("\x00")
|
|
51
|
+
else:
|
|
52
|
+
# As last option, try to convert to json
|
|
53
|
+
result[key] = json.loads(json.dumps(value))
|
|
54
|
+
except Exception:
|
|
55
|
+
continue
|
|
56
|
+
|
|
57
|
+
# Remove the 'reserved' fields as they are just filled with zeros
|
|
58
|
+
result.pop("reserved", None)
|
|
59
|
+
result.pop("hipReserved", None)
|
|
60
|
+
|
|
61
|
+
return result
|
|
62
|
+
|
|
63
|
+
|
|
35
64
|
class HipFunctions(GPUBackend):
|
|
36
|
-
"""Class that groups the HIP functions
|
|
65
|
+
"""Class that groups the HIP functions and maintains state about the device."""
|
|
37
66
|
|
|
38
67
|
def __init__(self, device=0, iterations=7, compiler_options=None, observers=None):
|
|
39
68
|
"""Instantiate HipFunctions object used for interacting with the HIP device.
|
|
@@ -72,6 +101,13 @@ class HipFunctions(GPUBackend):
|
|
|
72
101
|
env["device_name"] = self.name
|
|
73
102
|
env["iterations"] = self.iterations
|
|
74
103
|
env["compiler_options"] = compiler_options
|
|
104
|
+
env["pci_bus_id"] = props.pciBusID
|
|
105
|
+
env["pci_domain_id"] = props.pciDomainID
|
|
106
|
+
env["pci_device_id"] = props.pciDeviceID
|
|
107
|
+
env["uuid"] = str(uuid.UUID(bytes=props.uuid.bytes))
|
|
108
|
+
env["hip_driver_version"] = hip_check(hip.hipDriverGetVersion())
|
|
109
|
+
env["hip_runtime_version"] = hip_check(hip.hipRuntimeGetVersion())
|
|
110
|
+
env["device_properties"] = extract_safe_properties(props)
|
|
75
111
|
self.env = env
|
|
76
112
|
|
|
77
113
|
# Create stream and events
|
|
@@ -149,13 +185,16 @@ class HipFunctions(GPUBackend):
|
|
|
149
185
|
# Format kernel string
|
|
150
186
|
kernel_string = kernel_instance.kernel_string
|
|
151
187
|
kernel_name = kernel_instance.name
|
|
152
|
-
|
|
153
|
-
kernel_string = 'extern "C" {\n' + kernel_string + "\n}"
|
|
188
|
+
expression_name = kernel_name.encode()
|
|
154
189
|
|
|
155
190
|
# Create program
|
|
156
191
|
prog = hip_check(hiprtc.hiprtcCreateProgram(kernel_string.encode(), kernel_name.encode(), 0, [], []))
|
|
157
192
|
|
|
158
193
|
try:
|
|
194
|
+
# Add the kernel as an expression. This forces hiprtc to instantiate the kernel if it
|
|
195
|
+
# is templated or if it is in a namespace.
|
|
196
|
+
hip_check(hiprtc.hiprtcAddNameExpression(prog, expression_name))
|
|
197
|
+
|
|
159
198
|
# Get device properties
|
|
160
199
|
props = hip.hipDeviceProp_t()
|
|
161
200
|
hip_check(hip.hipGetDeviceProperties(props, 0))
|
|
@@ -174,6 +213,10 @@ class HipFunctions(GPUBackend):
|
|
|
174
213
|
hip_check(hiprtc.hiprtcGetProgramLog(prog, log))
|
|
175
214
|
raise RuntimeError(log.decode())
|
|
176
215
|
|
|
216
|
+
# Get the lowered name. This is the name that can be used in hipModuleGetFunction to
|
|
217
|
+
# get the kernel. For templated kernels, this differs from the original kernel name.
|
|
218
|
+
lowered_name = hip_check(hiprtc.hiprtcGetLoweredName(prog, expression_name))
|
|
219
|
+
|
|
177
220
|
# Get compiled code
|
|
178
221
|
code_size = hip_check(hiprtc.hiprtcGetCodeSize(prog))
|
|
179
222
|
code = bytearray(code_size)
|
|
@@ -182,7 +225,7 @@ class HipFunctions(GPUBackend):
|
|
|
182
225
|
# Load module and get function
|
|
183
226
|
module = hip_check(hip.hipModuleLoadData(code))
|
|
184
227
|
self.current_module = module
|
|
185
|
-
kernel = hip_check(hip.hipModuleGetFunction(module,
|
|
228
|
+
kernel = hip_check(hip.hipModuleGetFunction(module, lowered_name))
|
|
186
229
|
|
|
187
230
|
except Exception as e:
|
|
188
231
|
# Cleanup
|
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
from warnings import warn
|
|
3
3
|
|
|
4
4
|
import numpy as np
|
|
5
|
+
import uuid
|
|
6
|
+
import os
|
|
5
7
|
|
|
6
8
|
from kernel_tuner.backends.backend import GPUBackend
|
|
7
9
|
from kernel_tuner.observers.nvcuda import CudaRuntimeObserver
|
|
8
10
|
from kernel_tuner.util import SkippableFailure
|
|
9
|
-
from kernel_tuner.utils.nvcuda import cuda_error_check, to_valid_nvrtc_gpu_arch_cc
|
|
11
|
+
from kernel_tuner.utils.nvcuda import cuda_error_check, to_valid_nvrtc_gpu_arch_cc, find_cuda_home, _check
|
|
10
12
|
|
|
11
13
|
# embedded in try block to be able to generate documentation
|
|
12
14
|
# and run tests without cuda-python installed
|
|
@@ -74,9 +76,6 @@ class CudaFunctions(GPUBackend):
|
|
|
74
76
|
self.current_module = None
|
|
75
77
|
self.func = None
|
|
76
78
|
self.compiler_options = compiler_options or []
|
|
77
|
-
self.compiler_options_bytes = []
|
|
78
|
-
for option in self.compiler_options:
|
|
79
|
-
self.compiler_options_bytes.append(str(option).encode("UTF-8"))
|
|
80
79
|
|
|
81
80
|
# create a stream and events
|
|
82
81
|
err, self.stream = driver.cuStreamCreate(0)
|
|
@@ -85,34 +84,119 @@ class CudaFunctions(GPUBackend):
|
|
|
85
84
|
cuda_error_check(err)
|
|
86
85
|
err, self.end = driver.cuEventCreate(0)
|
|
87
86
|
cuda_error_check(err)
|
|
87
|
+
self.current_sm_percentage = 100
|
|
88
|
+
self.green_ctx_cache = {}
|
|
89
|
+
self.green_ctx = None
|
|
88
90
|
|
|
89
91
|
# default dynamically allocated shared memory size, can be overwritten using smem_args
|
|
90
92
|
self.smem_size = 0
|
|
91
93
|
|
|
92
|
-
# setup observers
|
|
93
|
-
self.observers = observers or []
|
|
94
|
-
self.observers.append(CudaRuntimeObserver(self))
|
|
95
|
-
for observer in self.observers:
|
|
96
|
-
observer.register_device(self)
|
|
97
|
-
|
|
98
94
|
# collect environment information
|
|
99
95
|
err, device_properties = runtime.cudaGetDeviceProperties(device)
|
|
100
96
|
cuda_error_check(err)
|
|
101
97
|
env = dict()
|
|
98
|
+
env["uuid"] = str(uuid.UUID(bytes=device_properties.uuid.bytes))
|
|
102
99
|
env["device_name"] = device_properties.name.decode()
|
|
103
100
|
env["cuda_version"] = driver.CUDA_VERSION
|
|
104
101
|
env["compute_capability"] = self.cc
|
|
105
102
|
env["iterations"] = self.iterations
|
|
106
103
|
env["compiler_options"] = self.compiler_options
|
|
107
104
|
env["device_properties"] = str(device_properties).replace("\n", ", ")
|
|
105
|
+
|
|
106
|
+
# We must use `cudaDeviceGetPCIBusId` to get the PCI bus string
|
|
107
|
+
# It returns a series of bytes containing a null byte, not a `str`
|
|
108
|
+
err, pci_bus = runtime.cudaDeviceGetPCIBusId(32, device) # 32 = length?
|
|
109
|
+
cuda_error_check(err)
|
|
110
|
+
env["pci_bus_id"] = pci_bus.decode("ascii").split("\x00", 1)[0]
|
|
111
|
+
|
|
108
112
|
self.env = env
|
|
109
113
|
self.name = env["device_name"]
|
|
110
114
|
|
|
115
|
+
# setup observers
|
|
116
|
+
self.observers = observers or []
|
|
117
|
+
self.observers.append(CudaRuntimeObserver(self))
|
|
118
|
+
for observer in self.observers:
|
|
119
|
+
observer.register_device(self)
|
|
120
|
+
|
|
111
121
|
def __del__(self):
|
|
122
|
+
# Cleanup streams and green contexts, if any
|
|
123
|
+
if self.green_ctx_cache:
|
|
124
|
+
for val in self.green_ctx_cache.values():
|
|
125
|
+
green_ctx, stream, _ = val
|
|
126
|
+
_check(driver.cuStreamDestroy(stream))
|
|
127
|
+
_check(driver.cuGreenCtxDestroy(green_ctx))
|
|
128
|
+
|
|
129
|
+
# Cleanup
|
|
112
130
|
for device_memory in self.allocations:
|
|
113
131
|
if isinstance(device_memory, driver.CUdeviceptr):
|
|
114
|
-
|
|
115
|
-
|
|
132
|
+
_check(driver.cuMemFree(device_memory))
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def set_sm_percentage(self, sm_percentage):
|
|
136
|
+
""" Set the active SM percentage
|
|
137
|
+
|
|
138
|
+
Create a CUDA green context owning ~`sm_percentage` of the device's SMs
|
|
139
|
+
and a stream bound to it. Kernels launched afterwards are restricted
|
|
140
|
+
to that SM partition. Green contexts are cached in self.green_ctx_cache.
|
|
141
|
+
The actual number of SMs in the partition may not exactly match the
|
|
142
|
+
requested percentage. An observer may be used to query:
|
|
143
|
+
|
|
144
|
+
* Currently assigned number of SMs: self.assigned_sm_count
|
|
145
|
+
* Currently requested SM percentage: self.current_sm_percentage
|
|
146
|
+
|
|
147
|
+
Requires: CUDA >= 12.4 and a GPU that supports SM partitioning.
|
|
148
|
+
"""
|
|
149
|
+
|
|
150
|
+
if not 0 < sm_percentage <= 100:
|
|
151
|
+
raise ValueError("sm_percentage must be in (0, 100]")
|
|
152
|
+
|
|
153
|
+
# Check if sm_percentage is already applied
|
|
154
|
+
if sm_percentage == self.current_sm_percentage:
|
|
155
|
+
return
|
|
156
|
+
|
|
157
|
+
# Check if this sm_percentage has been requested before
|
|
158
|
+
if sm_percentage in self.green_ctx_cache:
|
|
159
|
+
self.green_ctx, self.stream, self.assigned_sm_count = self.green_ctx_cache[sm_percentage]
|
|
160
|
+
self.current_sm_percentage = sm_percentage
|
|
161
|
+
return
|
|
162
|
+
|
|
163
|
+
# Get total SMs and desired percentage
|
|
164
|
+
total_sms = _check(driver.cuDeviceGetAttribute(
|
|
165
|
+
driver.CUdevice_attribute.CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT, self.device))
|
|
166
|
+
want = max(1, round(total_sms * sm_percentage / 100.0))
|
|
167
|
+
|
|
168
|
+
# Full SM resource pool of the device.
|
|
169
|
+
sm_resource = _check(driver.cuDeviceGetDevResource(
|
|
170
|
+
self.device, driver.CUdevResourceType.CU_DEV_RESOURCE_TYPE_SM))
|
|
171
|
+
|
|
172
|
+
# Split off one group of at least `want` SMs. The driver rounds up to the
|
|
173
|
+
# device's partitioning granularity, so the actual count may be larger.
|
|
174
|
+
groups, _nb, _remaining = _check(driver.cuDevSmResourceSplitByCount(
|
|
175
|
+
1, # number of groups requested
|
|
176
|
+
sm_resource, # input resource
|
|
177
|
+
0, # useFlags (0 = default)
|
|
178
|
+
want, # minCount of SMs per group
|
|
179
|
+
))
|
|
180
|
+
group = groups[0]
|
|
181
|
+
assigned = group.sm.smCount
|
|
182
|
+
|
|
183
|
+
# Descriptor -> green context.
|
|
184
|
+
desc = _check(driver.cuDevResourceGenerateDesc([group], 1))
|
|
185
|
+
green_ctx = _check(driver.cuGreenCtxCreate(
|
|
186
|
+
desc, self.device, driver.CUgreenCtxCreate_flags.CU_GREEN_CTX_DEFAULT_STREAM))
|
|
187
|
+
|
|
188
|
+
# A stream from the green context confines launches to its SMs.
|
|
189
|
+
stream = _check(driver.cuGreenCtxStreamCreate(
|
|
190
|
+
green_ctx,
|
|
191
|
+
driver.CUstream_flags.CU_STREAM_NON_BLOCKING,
|
|
192
|
+
0, # priority
|
|
193
|
+
))
|
|
194
|
+
self.green_ctx_cache[sm_percentage] = (green_ctx, stream, assigned)
|
|
195
|
+
self.green_ctx = green_ctx
|
|
196
|
+
self.stream = stream
|
|
197
|
+
self.assigned_sm_count = assigned
|
|
198
|
+
self.current_sm_percentage = sm_percentage
|
|
199
|
+
|
|
116
200
|
|
|
117
201
|
def ready_argument_list(self, arguments):
|
|
118
202
|
"""Ready argument list to be passed to the kernel, allocates gpu mem.
|
|
@@ -139,6 +223,7 @@ class CudaFunctions(GPUBackend):
|
|
|
139
223
|
gpu_args.append(arg)
|
|
140
224
|
return gpu_args
|
|
141
225
|
|
|
226
|
+
|
|
142
227
|
def compile(self, kernel_instance):
|
|
143
228
|
"""Call the CUDA compiler to compile the kernel, return the device function.
|
|
144
229
|
|
|
@@ -154,37 +239,60 @@ class CudaFunctions(GPUBackend):
|
|
|
154
239
|
"""
|
|
155
240
|
kernel_string = kernel_instance.kernel_string
|
|
156
241
|
kernel_name = kernel_instance.name
|
|
242
|
+
expression_name = str.encode(kernel_name)
|
|
243
|
+
compiler_options = list(self.compiler_options)
|
|
244
|
+
|
|
245
|
+
# Add -std=c++11
|
|
246
|
+
if not any(opt.startswith(("-std=", "--std=")) for opt in self.compiler_options):
|
|
247
|
+
compiler_options.append("--std=c++11")
|
|
157
248
|
|
|
158
|
-
#
|
|
159
|
-
if
|
|
160
|
-
|
|
249
|
+
# Add -arch
|
|
250
|
+
if not any(opt.startswith(("-arch", "--arch", "--gpu-architecture=")) for opt in self.compiler_options):
|
|
251
|
+
arch_val = to_valid_nvrtc_gpu_arch_cc(self.cc)
|
|
252
|
+
compiler_options.append(f"--gpu-architecture=compute_{arch_val}")
|
|
161
253
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
self.compiler_options.append(f"--gpu-architecture=compute_{to_valid_nvrtc_gpu_arch_cc(self.cc)}")
|
|
254
|
+
# Add CUDA home to include path
|
|
255
|
+
cuda_home = find_cuda_home()
|
|
256
|
+
if cuda_home:
|
|
257
|
+
cuda_include = os.path.join(cuda_home, "include")
|
|
258
|
+
compiler_options.append(f"-I{cuda_include}")
|
|
259
|
+
|
|
260
|
+
# nvrtcCompileProgram requires bytes instead of str
|
|
261
|
+
compiler_options = [str(opt).encode("UTF-8") for opt in compiler_options]
|
|
171
262
|
|
|
172
263
|
err, program = nvrtc.nvrtcCreateProgram(str.encode(kernel_string), b"CUDAProgram", 0, [], [])
|
|
173
264
|
try:
|
|
265
|
+
# Add the kernel as an expression. This is necessary for templated kernels to ensure that the
|
|
266
|
+
# compiler actually instantiates the kernel that we want to compile.
|
|
267
|
+
cuda_error_check(err)
|
|
268
|
+
err = nvrtc.nvrtcAddNameExpression(program, expression_name)
|
|
269
|
+
|
|
270
|
+
# Compile the program
|
|
174
271
|
cuda_error_check(err)
|
|
175
272
|
err = nvrtc.nvrtcCompileProgram(program, len(compiler_options), compiler_options)
|
|
273
|
+
|
|
274
|
+
# Get the PTX
|
|
176
275
|
cuda_error_check(err)
|
|
177
276
|
err, size = nvrtc.nvrtcGetPTXSize(program)
|
|
178
277
|
cuda_error_check(err)
|
|
179
278
|
buff = b" " * size
|
|
180
279
|
err = nvrtc.nvrtcGetPTX(program, buff)
|
|
181
280
|
cuda_error_check(err)
|
|
281
|
+
|
|
282
|
+
# Load the module
|
|
182
283
|
err, self.current_module = driver.cuModuleLoadData(np.char.array(buff))
|
|
183
284
|
if err == driver.CUresult.CUDA_ERROR_INVALID_PTX:
|
|
184
285
|
raise SkippableFailure("uses too much shared data")
|
|
185
286
|
else:
|
|
186
287
|
cuda_error_check(err)
|
|
187
|
-
|
|
288
|
+
|
|
289
|
+
# First, get the "lowered" name of the kernel (i.e., the name inside the PTX).
|
|
290
|
+
# After, we can use the lowered name to lookup the kernel in the module.
|
|
291
|
+
err, lowered_name = nvrtc.nvrtcGetLoweredName(program, expression_name)
|
|
292
|
+
cuda_error_check(err)
|
|
293
|
+
err, self.func = driver.cuModuleGetFunction(
|
|
294
|
+
self.current_module, lowered_name
|
|
295
|
+
)
|
|
188
296
|
cuda_error_check(err)
|
|
189
297
|
|
|
190
298
|
# get the number of registers per thread used in this kernel
|
|
@@ -130,15 +130,10 @@ class PyCudaFunctions(GPUBackend):
|
|
|
130
130
|
# default dynamically allocated shared memory size, can be overwritten using smem_args
|
|
131
131
|
self.smem_size = 0
|
|
132
132
|
|
|
133
|
-
# setup observers
|
|
134
|
-
self.observers = observers or []
|
|
135
|
-
self.observers.append(PyCudaRuntimeObserver(self))
|
|
136
|
-
for obs in self.observers:
|
|
137
|
-
obs.register_device(self)
|
|
138
|
-
|
|
139
133
|
# collect environment information
|
|
140
134
|
env = dict()
|
|
141
135
|
env["device_name"] = self.context.get_device().name()
|
|
136
|
+
env["pci_bus_id"] = self.context.get_device().pci_bus_id()
|
|
142
137
|
env["cuda_version"] = ".".join([str(i) for i in drv.get_version()])
|
|
143
138
|
env["compute_capability"] = self.cc
|
|
144
139
|
env["iterations"] = self.iterations
|
|
@@ -147,6 +142,12 @@ class PyCudaFunctions(GPUBackend):
|
|
|
147
142
|
self.env = env
|
|
148
143
|
self.name = env["device_name"]
|
|
149
144
|
|
|
145
|
+
# setup observers
|
|
146
|
+
self.observers = observers or []
|
|
147
|
+
self.observers.append(PyCudaRuntimeObserver(self))
|
|
148
|
+
for obs in self.observers:
|
|
149
|
+
obs.register_device(self)
|
|
150
|
+
|
|
150
151
|
def __del__(self):
|
|
151
152
|
for gpu_mem in self.allocations:
|
|
152
153
|
# if needed for when using mocks during testing
|