kernel-tuner 1.2.0__tar.gz → 1.3.1__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.2.0 → kernel_tuner-1.3.1}/PKG-INFO +5 -4
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/accuracy.py +33 -12
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/backends/cupy.py +0 -1
- kernel_tuner-1.3.1/kernel_tuner/backends/hip/__init__.py +1 -0
- {kernel_tuner-1.2.0/kernel_tuner/backends → kernel_tuner-1.3.1/kernel_tuner/backends/hip}/hip.py +1 -14
- kernel_tuner-1.3.1/kernel_tuner/backends/hip/util.py +18 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/backends/hypertuner.py +82 -27
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/backends/nvcuda.py +45 -52
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/core.py +5 -2
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/file_utils.py +24 -1
- kernel_tuner-1.3.1/kernel_tuner/hyper.py +215 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/integration.py +4 -4
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/interface.py +95 -43
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/observers/hip.py +2 -1
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/observers/nvcuda.py +8 -4
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/runners/simulation.py +28 -3
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/schema/T1/1.0.0/input-schema.json +2 -1
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/schema/T4/1.0.0/results-schema.json +5 -1
- kernel_tuner-1.3.1/kernel_tuner/searchspace.py +1594 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/strategies/basinhopping.py +2 -2
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/strategies/bayes_opt.py +11 -9
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/strategies/brute_force.py +1 -1
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/strategies/common.py +117 -37
- kernel_tuner-1.3.1/kernel_tuner/strategies/diff_evo.py +409 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/strategies/dual_annealing.py +6 -5
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/strategies/firefly_algorithm.py +10 -8
- kernel_tuner-1.3.1/kernel_tuner/strategies/genetic_algorithm.py +252 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/strategies/greedy_ils.py +9 -4
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/strategies/greedy_mls.py +2 -2
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/strategies/hillclimbers.py +1 -1
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/strategies/minimize.py +2 -2
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/strategies/pso.py +20 -14
- kernel_tuner-1.3.1/kernel_tuner/strategies/pyatf_strategies.py +123 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/strategies/random_sample.py +2 -2
- kernel_tuner-1.3.1/kernel_tuner/strategies/simulated_annealing.py +174 -0
- kernel_tuner-1.3.1/kernel_tuner/strategies/wrapper.py +56 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/util.py +39 -44
- kernel_tuner-1.3.1/kernel_tuner/utils/nvcuda.py +63 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/pyproject.toml +5 -3
- kernel_tuner-1.3.1/test/conftest.py +7 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/context.py +27 -5
- kernel_tuner-1.3.1/test/strategies/test_cache_file.json +394 -0
- kernel_tuner-1.3.1/test/strategies/test_diff_evo.py +189 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/strategies/test_genetic_algorithm.py +9 -4
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/strategies/test_strategies.py +55 -17
- kernel_tuner-1.3.1/test/test_cache_file_T1_input.json +82 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/test_compiler_functions.py +2 -2
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/test_cuda_functions.py +3 -3
- kernel_tuner-1.3.1/test/test_custom_optimizer.py +174 -0
- kernel_tuner-1.3.1/test/test_hyper.py +39 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/test_integration.py +6 -6
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/test_kernelbuilder.py +2 -2
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/test_runners.py +10 -4
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/test_searchspace.py +207 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/test_util_functions.py +0 -10
- kernel_tuner-1.3.1/test/utils/__init__.py +0 -0
- kernel_tuner-1.3.1/test/utils/nvcuda.py +11 -0
- kernel_tuner-1.3.1/test/vector_add.cu +6 -0
- kernel_tuner-1.2.0/kernel_tuner/hyper.py +0 -98
- kernel_tuner-1.2.0/kernel_tuner/searchspace.py +0 -839
- kernel_tuner-1.2.0/kernel_tuner/strategies/diff_evo.py +0 -42
- kernel_tuner-1.2.0/kernel_tuner/strategies/genetic_algorithm.py +0 -181
- kernel_tuner-1.2.0/kernel_tuner/strategies/simulated_annealing.py +0 -120
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/LICENSE +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/README.md +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/__init__.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/backends/__init__.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/backends/backend.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/backends/compiler.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/backends/opencl.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/backends/pycuda.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/energy/__init__.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/energy/energy.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/kernelbuilder.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/observers/__init__.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/observers/compiler.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/observers/cupy.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/observers/ncu.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/observers/nvml.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/observers/observer.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/observers/opencl.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/observers/pmt.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/observers/powersensor.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/observers/pycuda.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/observers/register.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/observers/tegra.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/runners/__init__.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/runners/runner.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/runners/sequential.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/schema/T4/1.0.0/metadata-schema.json +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/strategies/__init__.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/strategies/mls.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/strategies/ordered_greedy_mls.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/utils/__init__.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/kernel_tuner/utils/directives.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/__init__.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/convolution.cu +0 -0
- {kernel_tuner-1.2.0/test/utils → kernel_tuner-1.3.1/test/strategies}/__init__.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/strategies/test_bayesian_optimization.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/strategies/test_common.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/synthetic_fp32_cache_NVIDIA_RTX_A4000.json +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/test_T1_input.json +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/test_accuracy.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/test_backend.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/test_cache_file.json +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/test_common.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/test_core.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/test_cupy_functions.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/test_energy.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/test_file_utils.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/test_hip_functions.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/test_nvml_mocked.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/test_observers.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/test_opencl_functions.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/test_pycuda_functions.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/test_pycuda_mocked.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/test_time_budgets.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/test_toml_file.py +0 -0
- {kernel_tuner-1.2.0 → kernel_tuner-1.3.1}/test/utils/test_directives.py +0 -0
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: kernel_tuner
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.1
|
|
4
4
|
Summary: An easy to use CUDA/OpenCL kernel tuner in Python
|
|
5
|
-
License: Apache-2.0
|
|
5
|
+
License-Expression: Apache-2.0
|
|
6
|
+
License-File: LICENSE
|
|
6
7
|
Keywords: auto-tuning,gpu,computing,pycuda,cuda,pyopencl,opencl
|
|
7
8
|
Author: Ben van Werkhoven
|
|
8
9
|
Author-email: b.vanwerkhoven@esciencecenter.nl
|
|
@@ -43,7 +44,7 @@ Requires-Dist: pycuda (>=2025.1) ; extra == "cuda"
|
|
|
43
44
|
Requires-Dist: pynvml (>=11.4.1) ; extra == "cuda"
|
|
44
45
|
Requires-Dist: pyopencl ; extra == "cuda-opencl"
|
|
45
46
|
Requires-Dist: pyopencl ; extra == "opencl"
|
|
46
|
-
Requires-Dist: python-constraint2 (>=2.
|
|
47
|
+
Requires-Dist: python-constraint2 (>=2.4.0)
|
|
47
48
|
Requires-Dist: scikit-learn (>=1.0.2)
|
|
48
49
|
Requires-Dist: scipy (>=1.14.1)
|
|
49
50
|
Requires-Dist: xmltodict
|
|
@@ -58,22 +58,43 @@ class Tunable(UserDict):
|
|
|
58
58
|
|
|
59
59
|
def _find_bfloat16_if_available():
|
|
60
60
|
# Try to get bfloat16 if available.
|
|
61
|
-
|
|
62
|
-
from bfloat16 import bfloat16
|
|
63
|
-
return bfloat16
|
|
64
|
-
except ImportError:
|
|
65
|
-
pass
|
|
61
|
+
dtype = None
|
|
66
62
|
|
|
63
|
+
# get it via numpy if available
|
|
67
64
|
try:
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
except ImportError:
|
|
65
|
+
dtype = np.dtype("bfloat16")
|
|
66
|
+
except TypeError:
|
|
71
67
|
pass
|
|
72
68
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
69
|
+
# otherwise, try ml_dtypes
|
|
70
|
+
if dtype is None:
|
|
71
|
+
try:
|
|
72
|
+
from ml_dtypes import bfloat16
|
|
73
|
+
dtype = bfloat16
|
|
74
|
+
except ImportError:
|
|
75
|
+
pass
|
|
76
|
+
|
|
77
|
+
# otherwise, try jax
|
|
78
|
+
if dtype is None:
|
|
79
|
+
try:
|
|
80
|
+
from jax.numpy import bfloat16
|
|
81
|
+
dtype = bfloat16
|
|
82
|
+
except ImportError:
|
|
83
|
+
pass
|
|
84
|
+
|
|
85
|
+
# otherwise, try tensorflow
|
|
86
|
+
if dtype is None:
|
|
87
|
+
try:
|
|
88
|
+
from tensorflow import bfloat16
|
|
89
|
+
dtype = bfloat16.as_numpy_dtype
|
|
90
|
+
except ImportError:
|
|
91
|
+
pass
|
|
92
|
+
|
|
93
|
+
if dtype is None:
|
|
94
|
+
logging.warning(
|
|
95
|
+
"could not find `bfloat16` data type for numpy, "
|
|
96
|
+
+ "please install either the package `ml_dtypes`, `jax`, or `tensorflow`"
|
|
97
|
+
)
|
|
77
98
|
|
|
78
99
|
return None
|
|
79
100
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .hip import *
|
{kernel_tuner-1.2.0/kernel_tuner/backends → kernel_tuner-1.3.1/kernel_tuner/backends/hip}/hip.py
RENAMED
|
@@ -8,6 +8,7 @@ import numpy as np
|
|
|
8
8
|
|
|
9
9
|
from kernel_tuner.backends.backend import GPUBackend
|
|
10
10
|
from kernel_tuner.observers.hip import HipRuntimeObserver
|
|
11
|
+
from kernel_tuner.backends.hip.util import hip_check
|
|
11
12
|
|
|
12
13
|
try:
|
|
13
14
|
from hip import hip, hiprtc
|
|
@@ -31,20 +32,6 @@ dtype_map = {
|
|
|
31
32
|
|
|
32
33
|
hipSuccess = 0
|
|
33
34
|
|
|
34
|
-
|
|
35
|
-
def hip_check(call_result):
|
|
36
|
-
"""helper function to check return values of hip calls"""
|
|
37
|
-
err = call_result[0]
|
|
38
|
-
result = call_result[1:]
|
|
39
|
-
if len(result) == 1:
|
|
40
|
-
result = result[0]
|
|
41
|
-
if isinstance(err, hip.hipError_t) and err != hip.hipError_t.hipSuccess:
|
|
42
|
-
_, error_name = hip.hipGetErrorName(err)
|
|
43
|
-
_, error_str = hip.hipGetErrorString(err)
|
|
44
|
-
raise RuntimeError(f"{error_name}: {error_str}")
|
|
45
|
-
return result
|
|
46
|
-
|
|
47
|
-
|
|
48
35
|
class HipFunctions(GPUBackend):
|
|
49
36
|
"""Class that groups the HIP functions on maintains state about the device."""
|
|
50
37
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
try:
|
|
2
|
+
from hip import hip, hiprtc
|
|
3
|
+
except (ImportError, RuntimeError):
|
|
4
|
+
hip = None
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def hip_check(call_result):
|
|
8
|
+
"""helper function to check return values of hip calls"""
|
|
9
|
+
err = call_result[0]
|
|
10
|
+
result = call_result[1:]
|
|
11
|
+
if len(result) == 1:
|
|
12
|
+
result = result[0]
|
|
13
|
+
if isinstance(err, hip.hipError_t) and err != hip.hipError_t.hipSuccess:
|
|
14
|
+
_, error_name = hip.hipGetErrorName(err)
|
|
15
|
+
_, error_str = hip.hipGetErrorString(err)
|
|
16
|
+
raise RuntimeError(f"{error_name}: {error_str}")
|
|
17
|
+
return result
|
|
18
|
+
|
|
@@ -17,6 +17,8 @@ except ImportError:
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class ScoreObserver(BenchmarkObserver):
|
|
20
|
+
"""BenchmarkObserver subclass for registering the hyperparameter tuning score."""
|
|
21
|
+
|
|
20
22
|
def __init__(self, dev):
|
|
21
23
|
self.dev = dev
|
|
22
24
|
self.scores = []
|
|
@@ -33,13 +35,70 @@ class HypertunerFunctions(Backend):
|
|
|
33
35
|
"""Class for executing hyperparameter tuning."""
|
|
34
36
|
units = {}
|
|
35
37
|
|
|
36
|
-
def __init__(self, iterations):
|
|
38
|
+
def __init__(self, iterations, compiler_options=None):
|
|
37
39
|
self.iterations = iterations
|
|
40
|
+
self.compiler_options = compiler_options
|
|
38
41
|
self.observers = [ScoreObserver(self)]
|
|
39
42
|
self.name = platform.processor()
|
|
40
43
|
self.max_threads = 1024
|
|
41
44
|
self.last_score = None
|
|
42
45
|
|
|
46
|
+
# set the defaults
|
|
47
|
+
self.gpus = ["A100", "A4000", "MI250X"]
|
|
48
|
+
folder = "../autotuning_methodology/benchmark_hub/kernels"
|
|
49
|
+
self.applications = [
|
|
50
|
+
{
|
|
51
|
+
"name": "dedispersion_milo",
|
|
52
|
+
"folder": folder,
|
|
53
|
+
"input_file": "dedispersion_milo.json",
|
|
54
|
+
"objective_performance_keys": ["time"]
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"name": "hotspot_milo",
|
|
58
|
+
"folder": folder,
|
|
59
|
+
"input_file": "hotspot_milo.json",
|
|
60
|
+
"objective_performance_keys": ["GFLOP/s"]
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"name": "convolution_milo",
|
|
64
|
+
"folder": folder,
|
|
65
|
+
"input_file": "convolution_milo.json",
|
|
66
|
+
"objective_performance_keys": ["time"]
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"name": "gemm_milo",
|
|
70
|
+
"folder": folder,
|
|
71
|
+
"input_file": "gemm_milo.json",
|
|
72
|
+
"objective_performance_keys": ["time"]
|
|
73
|
+
}
|
|
74
|
+
]
|
|
75
|
+
# any additional settings
|
|
76
|
+
self.override = {
|
|
77
|
+
"experimental_groups_defaults": {
|
|
78
|
+
"repeats": 25,
|
|
79
|
+
"samples": self.iterations,
|
|
80
|
+
"minimum_fraction_of_budget_valid": 0.1,
|
|
81
|
+
"minimum_number_of_valid_search_iterations": 3,
|
|
82
|
+
},
|
|
83
|
+
"statistics_settings": {
|
|
84
|
+
"cutoff_percentile": 0.95,
|
|
85
|
+
"cutoff_percentile_start": 0.01,
|
|
86
|
+
"cutoff_type": "time",
|
|
87
|
+
"objective_time_keys": [
|
|
88
|
+
"all"
|
|
89
|
+
]
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
# override the defaults with compiler options if provided
|
|
94
|
+
if self.compiler_options is not None:
|
|
95
|
+
if "gpus" in self.compiler_options:
|
|
96
|
+
self.gpus = self.compiler_options["gpus"]
|
|
97
|
+
if "applications" in self.compiler_options:
|
|
98
|
+
self.applications = self.compiler_options["applications"]
|
|
99
|
+
if "override" in self.compiler_options:
|
|
100
|
+
self.override = self.compiler_options["override"]
|
|
101
|
+
|
|
43
102
|
# set the environment options
|
|
44
103
|
env = dict()
|
|
45
104
|
env["iterations"] = self.iterations
|
|
@@ -60,22 +119,6 @@ class HypertunerFunctions(Backend):
|
|
|
60
119
|
path = Path(__file__).parent.parent.parent / "hyperparamtuning"
|
|
61
120
|
path.mkdir(exist_ok=True)
|
|
62
121
|
|
|
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
122
|
# strategy settings
|
|
80
123
|
strategy: str = kernel_instance.arguments[0]
|
|
81
124
|
hyperparams = [{'name': k, 'value': v} for k, v in kernel_instance.params.items()]
|
|
@@ -88,16 +131,9 @@ class HypertunerFunctions(Backend):
|
|
|
88
131
|
'search_method_hyperparameters': hyperparams
|
|
89
132
|
}]
|
|
90
133
|
|
|
91
|
-
# any additional settings
|
|
92
|
-
override = {
|
|
93
|
-
"experimental_groups_defaults": {
|
|
94
|
-
"samples": self.iterations
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
134
|
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)
|
|
135
|
+
experiments_filepath = generate_experiment_file(name, path, searchspace_strategies, self.applications, self.gpus,
|
|
136
|
+
override=self.override, generate_unique_file=True, overwrite_existing_file=True)
|
|
101
137
|
return str(experiments_filepath)
|
|
102
138
|
|
|
103
139
|
def start_event(self):
|
|
@@ -114,12 +150,27 @@ class HypertunerFunctions(Backend):
|
|
|
114
150
|
return super().synchronize()
|
|
115
151
|
|
|
116
152
|
def run_kernel(self, func, gpu_args=None, threads=None, grid=None, stream=None):
|
|
153
|
+
# from cProfile import Profile
|
|
154
|
+
|
|
155
|
+
# # generate the experiments file
|
|
156
|
+
# experiments_filepath = Path(func)
|
|
157
|
+
|
|
158
|
+
# # run the methodology to get a fitness score for this configuration
|
|
159
|
+
# with Profile() as pr:
|
|
160
|
+
# scores = get_strategy_scores(str(experiments_filepath), full_validate_on_load=False)
|
|
161
|
+
# pr.dump_stats('diff_evo_hypertune_hotspot.prof')
|
|
162
|
+
# self.last_score = scores[list(scores.keys())[0]]['score']
|
|
163
|
+
# raise ValueError(scores)
|
|
164
|
+
|
|
117
165
|
# generate the experiments file
|
|
118
166
|
experiments_filepath = Path(func)
|
|
119
167
|
|
|
120
168
|
# run the methodology to get a fitness score for this configuration
|
|
121
|
-
scores = get_strategy_scores(str(experiments_filepath))
|
|
169
|
+
scores = get_strategy_scores(str(experiments_filepath), full_validate_on_load=False)
|
|
122
170
|
self.last_score = scores[list(scores.keys())[0]]['score']
|
|
171
|
+
|
|
172
|
+
# remove the experiments file
|
|
173
|
+
experiments_filepath.unlink()
|
|
123
174
|
|
|
124
175
|
def memset(self, allocation, value, size):
|
|
125
176
|
return super().memset(allocation, value, size)
|
|
@@ -129,3 +180,7 @@ class HypertunerFunctions(Backend):
|
|
|
129
180
|
|
|
130
181
|
def memcpy_htod(self, dest, src):
|
|
131
182
|
return super().memcpy_htod(dest, src)
|
|
183
|
+
|
|
184
|
+
def refresh_memory(self, device_memory, host_arguments, should_sync):
|
|
185
|
+
"""This is a no-op for the hypertuner backend, as it does not manage memory directly."""
|
|
186
|
+
pass
|
|
@@ -5,18 +5,23 @@ import numpy as np
|
|
|
5
5
|
|
|
6
6
|
from kernel_tuner.backends.backend import GPUBackend
|
|
7
7
|
from kernel_tuner.observers.nvcuda import CudaRuntimeObserver
|
|
8
|
-
from kernel_tuner.util import SkippableFailure
|
|
8
|
+
from kernel_tuner.util import SkippableFailure
|
|
9
|
+
from kernel_tuner.utils.nvcuda import cuda_error_check, to_valid_nvrtc_gpu_arch_cc
|
|
9
10
|
|
|
10
11
|
# embedded in try block to be able to generate documentation
|
|
11
12
|
# and run tests without cuda-python installed
|
|
12
13
|
try:
|
|
13
|
-
from cuda import
|
|
14
|
+
from cuda.bindings import driver, runtime, nvrtc
|
|
14
15
|
except ImportError:
|
|
15
|
-
|
|
16
|
+
try:
|
|
17
|
+
# backward compatibility hack for older cuda-python versions
|
|
18
|
+
from cuda import cuda as driver, cudart as runtime, nvrtc as nvrtc
|
|
19
|
+
except ImportError:
|
|
20
|
+
driver = None
|
|
16
21
|
|
|
17
22
|
|
|
18
23
|
class CudaFunctions(GPUBackend):
|
|
19
|
-
"""Class that groups the Cuda functions
|
|
24
|
+
"""Class that groups the Cuda functions and it maintains state about the device."""
|
|
20
25
|
|
|
21
26
|
def __init__(self, device=0, iterations=7, compiler_options=None, observers=None):
|
|
22
27
|
"""Instantiate CudaFunctions object used for interacting with the CUDA device.
|
|
@@ -38,34 +43,30 @@ class CudaFunctions(GPUBackend):
|
|
|
38
43
|
"""
|
|
39
44
|
self.allocations = []
|
|
40
45
|
self.texrefs = []
|
|
41
|
-
if not
|
|
46
|
+
if not driver:
|
|
42
47
|
raise ImportError(
|
|
43
48
|
"cuda-python not installed, install using 'pip install cuda-python', or check https://kerneltuner.github.io/kernel_tuner/stable/install.html#cuda-and-pycuda."
|
|
44
49
|
)
|
|
45
50
|
|
|
46
51
|
# initialize and select device
|
|
47
|
-
err =
|
|
52
|
+
err = driver.cuInit(0)
|
|
48
53
|
cuda_error_check(err)
|
|
49
|
-
err, self.device =
|
|
54
|
+
err, self.device = driver.cuDeviceGet(device)
|
|
50
55
|
cuda_error_check(err)
|
|
51
|
-
err, self.context =
|
|
56
|
+
err, self.context = driver.cuDevicePrimaryCtxRetain(device)
|
|
52
57
|
cuda_error_check(err)
|
|
53
58
|
if CudaFunctions.last_selected_device != device:
|
|
54
|
-
err =
|
|
59
|
+
err = driver.cuCtxSetCurrent(self.context)
|
|
55
60
|
cuda_error_check(err)
|
|
56
61
|
CudaFunctions.last_selected_device = device
|
|
57
62
|
|
|
58
63
|
# compute capabilities and device properties
|
|
59
|
-
err, major =
|
|
60
|
-
cudart.cudaDeviceAttr.cudaDevAttrComputeCapabilityMajor, device
|
|
61
|
-
)
|
|
64
|
+
err, major = runtime.cudaDeviceGetAttribute(runtime.cudaDeviceAttr.cudaDevAttrComputeCapabilityMajor, device)
|
|
62
65
|
cuda_error_check(err)
|
|
63
|
-
err, minor =
|
|
64
|
-
cudart.cudaDeviceAttr.cudaDevAttrComputeCapabilityMinor, device
|
|
65
|
-
)
|
|
66
|
+
err, minor = runtime.cudaDeviceGetAttribute(runtime.cudaDeviceAttr.cudaDevAttrComputeCapabilityMinor, device)
|
|
66
67
|
cuda_error_check(err)
|
|
67
|
-
err, self.max_threads =
|
|
68
|
-
|
|
68
|
+
err, self.max_threads = runtime.cudaDeviceGetAttribute(
|
|
69
|
+
runtime.cudaDeviceAttr.cudaDevAttrMaxThreadsPerBlock, device
|
|
69
70
|
)
|
|
70
71
|
cuda_error_check(err)
|
|
71
72
|
self.cc = f"{major}{minor}"
|
|
@@ -78,11 +79,11 @@ class CudaFunctions(GPUBackend):
|
|
|
78
79
|
self.compiler_options_bytes.append(str(option).encode("UTF-8"))
|
|
79
80
|
|
|
80
81
|
# create a stream and events
|
|
81
|
-
err, self.stream =
|
|
82
|
+
err, self.stream = driver.cuStreamCreate(0)
|
|
82
83
|
cuda_error_check(err)
|
|
83
|
-
err, self.start =
|
|
84
|
+
err, self.start = driver.cuEventCreate(0)
|
|
84
85
|
cuda_error_check(err)
|
|
85
|
-
err, self.end =
|
|
86
|
+
err, self.end = driver.cuEventCreate(0)
|
|
86
87
|
cuda_error_check(err)
|
|
87
88
|
|
|
88
89
|
# default dynamically allocated shared memory size, can be overwritten using smem_args
|
|
@@ -95,11 +96,11 @@ class CudaFunctions(GPUBackend):
|
|
|
95
96
|
observer.register_device(self)
|
|
96
97
|
|
|
97
98
|
# collect environment information
|
|
98
|
-
err, device_properties =
|
|
99
|
+
err, device_properties = runtime.cudaGetDeviceProperties(device)
|
|
99
100
|
cuda_error_check(err)
|
|
100
101
|
env = dict()
|
|
101
102
|
env["device_name"] = device_properties.name.decode()
|
|
102
|
-
env["cuda_version"] =
|
|
103
|
+
env["cuda_version"] = driver.CUDA_VERSION
|
|
103
104
|
env["compute_capability"] = self.cc
|
|
104
105
|
env["iterations"] = self.iterations
|
|
105
106
|
env["compiler_options"] = self.compiler_options
|
|
@@ -109,8 +110,8 @@ class CudaFunctions(GPUBackend):
|
|
|
109
110
|
|
|
110
111
|
def __del__(self):
|
|
111
112
|
for device_memory in self.allocations:
|
|
112
|
-
if isinstance(device_memory,
|
|
113
|
-
err =
|
|
113
|
+
if isinstance(device_memory, driver.CUdeviceptr):
|
|
114
|
+
err = driver.cuMemFree(device_memory)
|
|
114
115
|
cuda_error_check(err)
|
|
115
116
|
|
|
116
117
|
def ready_argument_list(self, arguments):
|
|
@@ -128,7 +129,7 @@ class CudaFunctions(GPUBackend):
|
|
|
128
129
|
for arg in arguments:
|
|
129
130
|
# if arg is a numpy array copy it to device
|
|
130
131
|
if isinstance(arg, np.ndarray):
|
|
131
|
-
err, device_memory =
|
|
132
|
+
err, device_memory = driver.cuMemAlloc(arg.nbytes)
|
|
132
133
|
cuda_error_check(err)
|
|
133
134
|
self.allocations.append(device_memory)
|
|
134
135
|
gpu_args.append(device_memory)
|
|
@@ -164,38 +165,30 @@ class CudaFunctions(GPUBackend):
|
|
|
164
165
|
if not any(["--std=" in opt for opt in self.compiler_options]):
|
|
165
166
|
self.compiler_options.append("--std=c++11")
|
|
166
167
|
if not any([b"--gpu-architecture=" in opt or b"-arch" in opt for opt in compiler_options]):
|
|
167
|
-
compiler_options.append(
|
|
168
|
-
f"--gpu-architecture=compute_{to_valid_nvrtc_gpu_arch_cc(self.cc)}".encode("UTF-8")
|
|
169
|
-
)
|
|
168
|
+
compiler_options.append(f"--gpu-architecture=compute_{to_valid_nvrtc_gpu_arch_cc(self.cc)}".encode("UTF-8"))
|
|
170
169
|
if not any(["--gpu-architecture=" in opt or "-arch" in opt for opt in self.compiler_options]):
|
|
171
170
|
self.compiler_options.append(f"--gpu-architecture=compute_{to_valid_nvrtc_gpu_arch_cc(self.cc)}")
|
|
172
171
|
|
|
173
|
-
err, program = nvrtc.nvrtcCreateProgram(
|
|
174
|
-
str.encode(kernel_string), b"CUDAProgram", 0, [], []
|
|
175
|
-
)
|
|
172
|
+
err, program = nvrtc.nvrtcCreateProgram(str.encode(kernel_string), b"CUDAProgram", 0, [], [])
|
|
176
173
|
try:
|
|
177
174
|
cuda_error_check(err)
|
|
178
|
-
err = nvrtc.nvrtcCompileProgram(
|
|
179
|
-
program, len(compiler_options), compiler_options
|
|
180
|
-
)
|
|
175
|
+
err = nvrtc.nvrtcCompileProgram(program, len(compiler_options), compiler_options)
|
|
181
176
|
cuda_error_check(err)
|
|
182
177
|
err, size = nvrtc.nvrtcGetPTXSize(program)
|
|
183
178
|
cuda_error_check(err)
|
|
184
179
|
buff = b" " * size
|
|
185
180
|
err = nvrtc.nvrtcGetPTX(program, buff)
|
|
186
181
|
cuda_error_check(err)
|
|
187
|
-
err, self.current_module =
|
|
188
|
-
if err ==
|
|
182
|
+
err, self.current_module = driver.cuModuleLoadData(np.char.array(buff))
|
|
183
|
+
if err == driver.CUresult.CUDA_ERROR_INVALID_PTX:
|
|
189
184
|
raise SkippableFailure("uses too much shared data")
|
|
190
185
|
else:
|
|
191
186
|
cuda_error_check(err)
|
|
192
|
-
err, self.func =
|
|
193
|
-
self.current_module, str.encode(kernel_name)
|
|
194
|
-
)
|
|
187
|
+
err, self.func = driver.cuModuleGetFunction(self.current_module, str.encode(kernel_name))
|
|
195
188
|
cuda_error_check(err)
|
|
196
189
|
|
|
197
190
|
# get the number of registers per thread used in this kernel
|
|
198
|
-
num_regs =
|
|
191
|
+
num_regs = driver.cuFuncGetAttribute(driver.CUfunction_attribute.CU_FUNC_ATTRIBUTE_NUM_REGS, self.func)
|
|
199
192
|
assert num_regs[0] == 0, f"Retrieving number of registers per thread unsuccesful: code {num_regs[0]}"
|
|
200
193
|
self.num_regs = num_regs[1]
|
|
201
194
|
|
|
@@ -210,18 +203,18 @@ class CudaFunctions(GPUBackend):
|
|
|
210
203
|
|
|
211
204
|
def start_event(self):
|
|
212
205
|
"""Records the event that marks the start of a measurement."""
|
|
213
|
-
err =
|
|
206
|
+
err = runtime.cudaEventRecord(self.start, self.stream)
|
|
214
207
|
cuda_error_check(err)
|
|
215
208
|
|
|
216
209
|
def stop_event(self):
|
|
217
210
|
"""Records the event that marks the end of a measurement."""
|
|
218
|
-
err =
|
|
211
|
+
err = runtime.cudaEventRecord(self.end, self.stream)
|
|
219
212
|
cuda_error_check(err)
|
|
220
213
|
|
|
221
214
|
def kernel_finished(self):
|
|
222
215
|
"""Returns True if the kernel has finished, False otherwise."""
|
|
223
|
-
err =
|
|
224
|
-
if err[0] ==
|
|
216
|
+
err = runtime.cudaEventQuery(self.end)
|
|
217
|
+
if err[0] == runtime.cudaError_t.cudaSuccess:
|
|
225
218
|
return True
|
|
226
219
|
else:
|
|
227
220
|
return False
|
|
@@ -229,7 +222,7 @@ class CudaFunctions(GPUBackend):
|
|
|
229
222
|
@staticmethod
|
|
230
223
|
def synchronize():
|
|
231
224
|
"""Halts execution until device has finished its tasks."""
|
|
232
|
-
err =
|
|
225
|
+
err = runtime.cudaDeviceSynchronize()
|
|
233
226
|
cuda_error_check(err)
|
|
234
227
|
|
|
235
228
|
def copy_constant_memory_args(self, cmem_args):
|
|
@@ -243,9 +236,9 @@ class CudaFunctions(GPUBackend):
|
|
|
243
236
|
:type cmem_args: dict( string: numpy.ndarray, ... )
|
|
244
237
|
"""
|
|
245
238
|
for k, v in cmem_args.items():
|
|
246
|
-
err, symbol, _ =
|
|
239
|
+
err, symbol, _ = driver.cuModuleGetGlobal(self.current_module, str.encode(k))
|
|
247
240
|
cuda_error_check(err)
|
|
248
|
-
err =
|
|
241
|
+
err = driver.cuMemcpyHtoD(symbol, v, v.nbytes)
|
|
249
242
|
cuda_error_check(err)
|
|
250
243
|
|
|
251
244
|
def copy_shared_memory_args(self, smem_args):
|
|
@@ -284,12 +277,12 @@ class CudaFunctions(GPUBackend):
|
|
|
284
277
|
stream = self.stream
|
|
285
278
|
arg_types = list()
|
|
286
279
|
for arg in gpu_args:
|
|
287
|
-
if isinstance(arg,
|
|
280
|
+
if isinstance(arg, driver.CUdeviceptr):
|
|
288
281
|
arg_types.append(None)
|
|
289
282
|
else:
|
|
290
283
|
arg_types.append(np.ctypeslib.as_ctypes_type(arg.dtype))
|
|
291
284
|
kernel_args = (tuple(gpu_args), tuple(arg_types))
|
|
292
|
-
err =
|
|
285
|
+
err = driver.cuLaunchKernel(
|
|
293
286
|
func,
|
|
294
287
|
grid[0],
|
|
295
288
|
grid[1],
|
|
@@ -318,7 +311,7 @@ class CudaFunctions(GPUBackend):
|
|
|
318
311
|
:type size: int
|
|
319
312
|
|
|
320
313
|
"""
|
|
321
|
-
err =
|
|
314
|
+
err = runtime.cudaMemset(allocation, value, size)
|
|
322
315
|
cuda_error_check(err)
|
|
323
316
|
|
|
324
317
|
@staticmethod
|
|
@@ -331,7 +324,7 @@ class CudaFunctions(GPUBackend):
|
|
|
331
324
|
:param src: A GPU memory allocation unit
|
|
332
325
|
:type src: cuda.CUdeviceptr
|
|
333
326
|
"""
|
|
334
|
-
err =
|
|
327
|
+
err = driver.cuMemcpyDtoH(dest, src, dest.nbytes)
|
|
335
328
|
cuda_error_check(err)
|
|
336
329
|
|
|
337
330
|
@staticmethod
|
|
@@ -344,7 +337,7 @@ class CudaFunctions(GPUBackend):
|
|
|
344
337
|
:param src: A numpy array in host memory to store the data
|
|
345
338
|
:type src: numpy.ndarray
|
|
346
339
|
"""
|
|
347
|
-
err =
|
|
340
|
+
err = driver.cuMemcpyHtoD(dest, src, src.nbytes)
|
|
348
341
|
cuda_error_check(err)
|
|
349
342
|
|
|
350
343
|
units = {"time": "ms"}
|
|
@@ -315,10 +315,13 @@ class DeviceInterface(object):
|
|
|
315
315
|
observers=observers,
|
|
316
316
|
)
|
|
317
317
|
elif lang.upper() == "HYPERTUNER":
|
|
318
|
-
dev = HypertunerFunctions(
|
|
318
|
+
dev = HypertunerFunctions(
|
|
319
|
+
iterations=iterations,
|
|
320
|
+
compiler_options=compiler_options
|
|
321
|
+
)
|
|
319
322
|
self.requires_warmup = False
|
|
320
323
|
else:
|
|
321
|
-
raise
|
|
324
|
+
raise NotImplementedError(
|
|
322
325
|
"Sorry, support for languages other than CUDA, OpenCL, HIP, C, and Fortran is not implemented yet"
|
|
323
326
|
)
|
|
324
327
|
self.dev = dev
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import json
|
|
4
4
|
import subprocess
|
|
5
5
|
from importlib.metadata import PackageNotFoundError, requires, version
|
|
6
|
+
from importlib.util import spec_from_file_location, module_from_spec
|
|
6
7
|
from pathlib import Path
|
|
7
8
|
from sys import platform
|
|
8
9
|
|
|
@@ -152,7 +153,7 @@ def get_t4_results(results, tune_params, objective="time"):
|
|
|
152
153
|
|
|
153
154
|
# write output_data to a JSON file
|
|
154
155
|
version, _ = output_file_schema("results")
|
|
155
|
-
output_json = dict(results=output_data, schema_version=version, metadata={'timeunit': '
|
|
156
|
+
output_json = dict(results=output_data, schema_version=version, metadata={'timeunit': 'milliseconds'})
|
|
156
157
|
return output_json
|
|
157
158
|
|
|
158
159
|
def store_output_file(output_filename: str, results, tune_params, objective="time"):
|
|
@@ -302,3 +303,25 @@ def store_metadata_file(metadata_filename: str):
|
|
|
302
303
|
with open(metadata_filenamepath, "w+") as fh:
|
|
303
304
|
json.dump(metadata_json, fh, indent=" ")
|
|
304
305
|
|
|
306
|
+
def import_class_from_file(file_path: Path, class_name):
|
|
307
|
+
"""Import a class from a file."""
|
|
308
|
+
|
|
309
|
+
def load_module(module_name):
|
|
310
|
+
spec = spec_from_file_location(module_name, file_path)
|
|
311
|
+
if spec is None:
|
|
312
|
+
raise ImportError(f"Could not load spec from {file_path}")
|
|
313
|
+
|
|
314
|
+
# create a module from the spec and execute it
|
|
315
|
+
module = module_from_spec(spec)
|
|
316
|
+
spec.loader.exec_module(module)
|
|
317
|
+
if not hasattr(module, class_name):
|
|
318
|
+
raise ImportError(f"Module '{module_name}' has no class '{class_name}'")
|
|
319
|
+
return module
|
|
320
|
+
|
|
321
|
+
try:
|
|
322
|
+
module = load_module(file_path.stem)
|
|
323
|
+
except ImportError:
|
|
324
|
+
module = load_module(f"{file_path.parent.stem}.{file_path.stem}")
|
|
325
|
+
|
|
326
|
+
# return the class from the module
|
|
327
|
+
return getattr(module, class_name)
|