kernel-tuner 0.1.8__tar.gz → 0.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-0.1.8 → kernel_tuner-0.2.0}/PKG-INFO +41 -19
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/README.rst +33 -17
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/c.py +57 -32
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/cuda.py +16 -11
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/interface.py +26 -1
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/strategies/basinhopping.py +0 -1
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/strategies/diff_evo.py +8 -27
- kernel_tuner-0.2.0/kernel_tuner/strategies/firefly_algorithm.py +116 -0
- kernel_tuner-0.2.0/kernel_tuner/strategies/genetic_algorithm.py +117 -0
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/strategies/minimize.py +2 -4
- kernel_tuner-0.2.0/kernel_tuner/strategies/pso.py +113 -0
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/strategies/random_sample.py +6 -2
- kernel_tuner-0.2.0/kernel_tuner/strategies/simulated_annealing.py +117 -0
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/util.py +28 -24
- kernel_tuner-0.2.0/kernel_tuner/wrappers.py +121 -0
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner.egg-info/PKG-INFO +41 -19
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner.egg-info/SOURCES.txt +5 -0
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/setup.py +1 -1
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/test/test_c_functions.py +21 -2
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/test/test_cuda_mocked.py +19 -11
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/test/test_interface.py +3 -3
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/test/test_util_functions.py +22 -37
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/LICENSE +0 -0
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/MANIFEST.in +0 -0
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/__init__.py +0 -0
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/core.py +0 -0
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/opencl.py +0 -0
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/runners/__init__.py +0 -0
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/runners/noodles.py +0 -0
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/runners/sequential.py +0 -0
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/strategies/__init__.py +0 -0
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/strategies/brute_force.py +0 -0
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner.egg-info/dependency_links.txt +0 -0
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner.egg-info/requires.txt +0 -0
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner.egg-info/top_level.txt +0 -0
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/setup.cfg +0 -0
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/test/test_cuda_functions.py +0 -0
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/test/test_device_interface.py +0 -0
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/test/test_minimize.py +0 -0
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/test/test_opencl_functions.py +0 -0
- {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/test/test_runners.py +0 -0
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
Metadata-Version:
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
2
|
Name: kernel_tuner
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: A simple CUDA/OpenCL kernel tuner in Python
|
|
5
5
|
Home-page: http://benvanwerkhoven.github.io/kernel_tuner/
|
|
6
6
|
Author: Ben van Werkhoven
|
|
7
7
|
Author-email: b.vanwerkhoven@esciencecenter.nl
|
|
8
8
|
License: Apache 2.0
|
|
9
|
-
Description: Kernel Tuner
|
|
10
|
-
|
|
9
|
+
Description: Kernel Tuner
|
|
10
|
+
============
|
|
11
11
|
|
|
12
|
-
|Build Status| |Codacy Badge| |Codacy Badge2|
|
|
12
|
+
|Build Status| |Codacy Badge| |Codacy Badge2| |PyPi Badge|
|
|
13
13
|
|
|
14
14
|
Kernel Tuner simplifies the software development of optimized and auto-tuned GPU programs, by enabling Python-based unit testing of GPU code and making it easy to develop scripts for auto-tuning GPU kernels. This also means no extensive changes and no new dependencies are required in the kernel code. The kernels can still be compiled and used as normal from any host programming language.
|
|
15
15
|
|
|
@@ -99,6 +99,23 @@ Description: Kernel Tuner: A simple CUDA/OpenCL Auto-Tuner in Python
|
|
|
99
99
|
and in the `Kernel Tuner
|
|
100
100
|
documentation pages <http://benvanwerkhoven.github.io/kernel_tuner/index.html>`__.
|
|
101
101
|
|
|
102
|
+
Search strategies for tuning
|
|
103
|
+
----------------------------
|
|
104
|
+
|
|
105
|
+
Kernel Tuner supports many optimization algorithms to accelerate the auto-tuning process. Currently
|
|
106
|
+
implemented search algorithms are: Brute Force (default), Nelder-Mead, Powell, CG, BFGS, L-BFGS-B, TNC,
|
|
107
|
+
COBYLA, SLSQP, Random Search, Basinhopping, Differential Evolution, a Genetic Algorithm, Particle Swarm
|
|
108
|
+
Optimization, the Firefly Algorithm, and Simulated Annealing.
|
|
109
|
+
|
|
110
|
+
.. image:: doc/gemm-amd-summary.png
|
|
111
|
+
:width: 100%
|
|
112
|
+
:align: center
|
|
113
|
+
|
|
114
|
+
Using a search strategy is easy, you only need to specify to ``tune_kernel`` which strategy and method
|
|
115
|
+
you would like to use, for example ``strategy="genetic_algorithm"`` or ``strategy="basinhopping",
|
|
116
|
+
method="Powell"``. For a full overview of the supported search strategies and methods please see the `user
|
|
117
|
+
api documentation <http://benvanwerkhoven.github.io/kernel_tuner/user-api.html>`__.
|
|
118
|
+
|
|
102
119
|
Tuning host and kernel code
|
|
103
120
|
---------------------------
|
|
104
121
|
|
|
@@ -113,12 +130,6 @@ Description: Kernel Tuner: A simple CUDA/OpenCL Auto-Tuner in Python
|
|
|
113
130
|
`documentation <http://benvanwerkhoven.github.io/kernel_tuner/hostcode.html>`__
|
|
114
131
|
for a detailed explanation of the kernel tuner Python script.
|
|
115
132
|
|
|
116
|
-
Search strategies for tuning
|
|
117
|
-
----------------------------
|
|
118
|
-
|
|
119
|
-
Kernel Tuner supports several strategies: brute_force (default), random_sample, minimize, basinhopping, and diff_evo (differential
|
|
120
|
-
evolution). Using different strategies is easy, you only need to specify to ``tune_kernel`` which strategy you would like to use, for example: ``strategy="basinhopping", method="TNC"``. For a full overview of the supported search strategies and methods please see the
|
|
121
|
-
`user api <http://benvanwerkhoven.github.io/kernel_tuner/user-api.html>`__.
|
|
122
133
|
|
|
123
134
|
Correctness verification
|
|
124
135
|
------------------------
|
|
@@ -140,23 +151,26 @@ Description: Kernel Tuner: A simple CUDA/OpenCL Auto-Tuner in Python
|
|
|
140
151
|
|
|
141
152
|
Citation
|
|
142
153
|
--------
|
|
143
|
-
A scientific paper about
|
|
154
|
+
A scientific paper about Kernel Tuner has been accepted for publication, please cite
|
|
155
|
+
Kernel Tuner as follows:
|
|
144
156
|
|
|
145
157
|
.. code:: latex
|
|
146
158
|
|
|
147
|
-
@
|
|
148
|
-
author
|
|
149
|
-
title
|
|
150
|
-
|
|
159
|
+
@article{kerneltuner,
|
|
160
|
+
author = {Ben van Werkhoven},
|
|
161
|
+
title = {Kernel Tuner: A search-optimizing GPU code auto-tuner},
|
|
162
|
+
journal = {Future Generation Computer Systems},
|
|
163
|
+
year = {2019},
|
|
164
|
+
volume = {90},
|
|
165
|
+
pages = {347-358},
|
|
166
|
+
doi = {https://doi.org/10.1016/j.future.2018.08.004},
|
|
151
167
|
}
|
|
152
168
|
|
|
153
169
|
Related work
|
|
154
170
|
------------
|
|
155
171
|
|
|
156
172
|
You may also like `CLTune <https://github.com/CNugteren/CLTune>`__ by
|
|
157
|
-
Cedric Nugteren. CLTune is a C++ library for kernel tuning
|
|
158
|
-
various advanced features like machine learning to optimize the time
|
|
159
|
-
spent on tuning kernels.
|
|
173
|
+
Cedric Nugteren. CLTune is a C++ library for kernel tuning.
|
|
160
174
|
|
|
161
175
|
.. |Build Status| image:: https://api.travis-ci.org/benvanwerkhoven/kernel_tuner.svg?branch=master
|
|
162
176
|
:target: https://travis-ci.org/benvanwerkhoven/kernel_tuner
|
|
@@ -164,6 +178,8 @@ Description: Kernel Tuner: A simple CUDA/OpenCL Auto-Tuner in Python
|
|
|
164
178
|
:target: https://www.codacy.com/app/b-vanwerkhoven/kernel_tuner
|
|
165
179
|
.. |Codacy Badge2| image:: https://api.codacy.com/project/badge/coverage/016dc85044ab4d57b777449d93275608
|
|
166
180
|
:target: https://www.codacy.com/app/b-vanwerkhoven/kernel_tuner
|
|
181
|
+
.. |PyPi Badge| image:: https://img.shields.io/pypi/v/kernel_tuner.svg?colorB=blue
|
|
182
|
+
:target: https://pypi.python.org/pypi/kernel_tuner/
|
|
167
183
|
|
|
168
184
|
Keywords: auto-tuning gpu computing pycuda cuda pyopencl opencl
|
|
169
185
|
Platform: UNKNOWN
|
|
@@ -180,3 +196,9 @@ Classifier: Topic :: Scientific/Engineering
|
|
|
180
196
|
Classifier: Topic :: Software Development
|
|
181
197
|
Classifier: Topic :: System :: Distributed Computing
|
|
182
198
|
Classifier: Development Status :: 4 - Beta
|
|
199
|
+
Provides-Extra: cuda_opencl
|
|
200
|
+
Provides-Extra: cuda
|
|
201
|
+
Provides-Extra: dev
|
|
202
|
+
Provides-Extra: tutorial
|
|
203
|
+
Provides-Extra: opencl
|
|
204
|
+
Provides-Extra: doc
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
Kernel Tuner
|
|
2
|
-
|
|
1
|
+
Kernel Tuner
|
|
2
|
+
============
|
|
3
3
|
|
|
4
|
-
|Build Status| |Codacy Badge| |Codacy Badge2|
|
|
4
|
+
|Build Status| |Codacy Badge| |Codacy Badge2| |PyPi Badge|
|
|
5
5
|
|
|
6
6
|
Kernel Tuner simplifies the software development of optimized and auto-tuned GPU programs, by enabling Python-based unit testing of GPU code and making it easy to develop scripts for auto-tuning GPU kernels. This also means no extensive changes and no new dependencies are required in the kernel code. The kernels can still be compiled and used as normal from any host programming language.
|
|
7
7
|
|
|
@@ -91,6 +91,23 @@ You can find many - more extensive - example codes, in the
|
|
|
91
91
|
and in the `Kernel Tuner
|
|
92
92
|
documentation pages <http://benvanwerkhoven.github.io/kernel_tuner/index.html>`__.
|
|
93
93
|
|
|
94
|
+
Search strategies for tuning
|
|
95
|
+
----------------------------
|
|
96
|
+
|
|
97
|
+
Kernel Tuner supports many optimization algorithms to accelerate the auto-tuning process. Currently
|
|
98
|
+
implemented search algorithms are: Brute Force (default), Nelder-Mead, Powell, CG, BFGS, L-BFGS-B, TNC,
|
|
99
|
+
COBYLA, SLSQP, Random Search, Basinhopping, Differential Evolution, a Genetic Algorithm, Particle Swarm
|
|
100
|
+
Optimization, the Firefly Algorithm, and Simulated Annealing.
|
|
101
|
+
|
|
102
|
+
.. image:: doc/gemm-amd-summary.png
|
|
103
|
+
:width: 100%
|
|
104
|
+
:align: center
|
|
105
|
+
|
|
106
|
+
Using a search strategy is easy, you only need to specify to ``tune_kernel`` which strategy and method
|
|
107
|
+
you would like to use, for example ``strategy="genetic_algorithm"`` or ``strategy="basinhopping",
|
|
108
|
+
method="Powell"``. For a full overview of the supported search strategies and methods please see the `user
|
|
109
|
+
api documentation <http://benvanwerkhoven.github.io/kernel_tuner/user-api.html>`__.
|
|
110
|
+
|
|
94
111
|
Tuning host and kernel code
|
|
95
112
|
---------------------------
|
|
96
113
|
|
|
@@ -105,12 +122,6 @@ and the
|
|
|
105
122
|
`documentation <http://benvanwerkhoven.github.io/kernel_tuner/hostcode.html>`__
|
|
106
123
|
for a detailed explanation of the kernel tuner Python script.
|
|
107
124
|
|
|
108
|
-
Search strategies for tuning
|
|
109
|
-
----------------------------
|
|
110
|
-
|
|
111
|
-
Kernel Tuner supports several strategies: brute_force (default), random_sample, minimize, basinhopping, and diff_evo (differential
|
|
112
|
-
evolution). Using different strategies is easy, you only need to specify to ``tune_kernel`` which strategy you would like to use, for example: ``strategy="basinhopping", method="TNC"``. For a full overview of the supported search strategies and methods please see the
|
|
113
|
-
`user api <http://benvanwerkhoven.github.io/kernel_tuner/user-api.html>`__.
|
|
114
125
|
|
|
115
126
|
Correctness verification
|
|
116
127
|
------------------------
|
|
@@ -132,23 +143,26 @@ Please see the `Contributions Guide <http://benvanwerkhoven.github.io/kernel_tun
|
|
|
132
143
|
|
|
133
144
|
Citation
|
|
134
145
|
--------
|
|
135
|
-
A scientific paper about
|
|
146
|
+
A scientific paper about Kernel Tuner has been accepted for publication, please cite
|
|
147
|
+
Kernel Tuner as follows:
|
|
136
148
|
|
|
137
149
|
.. code:: latex
|
|
138
150
|
|
|
139
|
-
@
|
|
140
|
-
author
|
|
141
|
-
title
|
|
142
|
-
|
|
151
|
+
@article{kerneltuner,
|
|
152
|
+
author = {Ben van Werkhoven},
|
|
153
|
+
title = {Kernel Tuner: A search-optimizing GPU code auto-tuner},
|
|
154
|
+
journal = {Future Generation Computer Systems},
|
|
155
|
+
year = {2019},
|
|
156
|
+
volume = {90},
|
|
157
|
+
pages = {347-358},
|
|
158
|
+
doi = {https://doi.org/10.1016/j.future.2018.08.004},
|
|
143
159
|
}
|
|
144
160
|
|
|
145
161
|
Related work
|
|
146
162
|
------------
|
|
147
163
|
|
|
148
164
|
You may also like `CLTune <https://github.com/CNugteren/CLTune>`__ by
|
|
149
|
-
Cedric Nugteren. CLTune is a C++ library for kernel tuning
|
|
150
|
-
various advanced features like machine learning to optimize the time
|
|
151
|
-
spent on tuning kernels.
|
|
165
|
+
Cedric Nugteren. CLTune is a C++ library for kernel tuning.
|
|
152
166
|
|
|
153
167
|
.. |Build Status| image:: https://api.travis-ci.org/benvanwerkhoven/kernel_tuner.svg?branch=master
|
|
154
168
|
:target: https://travis-ci.org/benvanwerkhoven/kernel_tuner
|
|
@@ -156,3 +170,5 @@ spent on tuning kernels.
|
|
|
156
170
|
:target: https://www.codacy.com/app/b-vanwerkhoven/kernel_tuner
|
|
157
171
|
.. |Codacy Badge2| image:: https://api.codacy.com/project/badge/coverage/016dc85044ab4d57b777449d93275608
|
|
158
172
|
:target: https://www.codacy.com/app/b-vanwerkhoven/kernel_tuner
|
|
173
|
+
.. |PyPi Badge| image:: https://img.shields.io/pypi/v/kernel_tuner.svg?colorB=blue
|
|
174
|
+
:target: https://pypi.python.org/pypi/kernel_tuner/
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
""" This module contains the functionality for running and compiling C functions """
|
|
2
2
|
|
|
3
|
+
from collections import namedtuple
|
|
3
4
|
import subprocess
|
|
4
5
|
import platform
|
|
5
6
|
import errno
|
|
7
|
+
import re
|
|
6
8
|
import logging
|
|
7
9
|
import ctypes as C
|
|
8
10
|
import _ctypes
|
|
@@ -12,6 +14,15 @@ import numpy.ctypeslib
|
|
|
12
14
|
|
|
13
15
|
from kernel_tuner.util import get_temp_filename, delete_temp_file, write_file
|
|
14
16
|
|
|
17
|
+
dtype_map = {"int8": C.c_int8,
|
|
18
|
+
"int16": C.c_int16,
|
|
19
|
+
"int32": C.c_int32,
|
|
20
|
+
"int64": C.c_int64,
|
|
21
|
+
"float32": C.c_float,
|
|
22
|
+
"float64": C.c_double}
|
|
23
|
+
|
|
24
|
+
Argument = namedtuple("Argument", ["type", "shape"])
|
|
25
|
+
|
|
15
26
|
|
|
16
27
|
class CFunctions(object):
|
|
17
28
|
"""Class that groups the code for running and compiling C functions"""
|
|
@@ -67,31 +78,23 @@ class CFunctions(object):
|
|
|
67
78
|
:returns: A list of arguments that can be passed to the C function.
|
|
68
79
|
:rtype: list()
|
|
69
80
|
"""
|
|
70
|
-
ctype_args = []
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
numpy.float32: C.c_float,
|
|
79
|
-
numpy.float64: C.c_double}
|
|
80
|
-
|
|
81
|
-
for arg in arguments:
|
|
81
|
+
ctype_args = [None for _ in arguments]
|
|
82
|
+
self.arg_mapping = dict()
|
|
83
|
+
|
|
84
|
+
for i, arg in enumerate(arguments):
|
|
85
|
+
if not isinstance(arg, (numpy.ndarray, numpy.generic)):
|
|
86
|
+
raise TypeError("Argument is not numpy ndarray or numpy scalar %s" % type(arg))
|
|
87
|
+
dtype_str = str(arg.dtype)
|
|
88
|
+
arg_info = Argument(dtype_str, arg.shape)
|
|
82
89
|
if isinstance(arg, numpy.ndarray):
|
|
83
|
-
dtype_str = str(arg.dtype)
|
|
84
90
|
if dtype_str in dtype_map.keys():
|
|
85
|
-
ctype_args
|
|
91
|
+
ctype_args[i] = arg.ctypes.data_as(C.POINTER(dtype_map[dtype_str]))
|
|
86
92
|
else:
|
|
87
93
|
raise TypeError("unknown dtype for ndarray")
|
|
88
|
-
self.arg_mapping[str(ctype_args[
|
|
89
|
-
elif isinstance(arg,
|
|
90
|
-
ctype_args
|
|
91
|
-
self.arg_mapping[str(
|
|
92
|
-
else:
|
|
93
|
-
raise TypeError("Argument is not numpy ndarray or numpy scalar %s" % type(arg))
|
|
94
|
-
|
|
94
|
+
self.arg_mapping[str(ctype_args[i])] = arg_info
|
|
95
|
+
elif isinstance(arg, numpy.generic):
|
|
96
|
+
ctype_args[i] = dtype_map[dtype_str](arg)
|
|
97
|
+
self.arg_mapping[str(i)] = arg_info
|
|
95
98
|
return ctype_args
|
|
96
99
|
|
|
97
100
|
|
|
@@ -113,25 +116,35 @@ class CFunctions(object):
|
|
|
113
116
|
if self.lib != None:
|
|
114
117
|
self.cleanup_lib()
|
|
115
118
|
|
|
116
|
-
suffix = ".cc"
|
|
117
|
-
|
|
118
|
-
if not "extern \"C\"" in kernel_string:
|
|
119
|
-
kernel_string = "extern \"C\" {\n" + kernel_string + "\n}"
|
|
120
|
-
|
|
121
119
|
compiler_options = ["-fPIC"]
|
|
122
|
-
|
|
120
|
+
|
|
121
|
+
#detect openmp
|
|
122
|
+
if "#include <omp.h>" in kernel_string or "use omp_lib" in kernel_string:
|
|
123
123
|
logging.debug('set using_openmp to true')
|
|
124
124
|
self.using_openmp = True
|
|
125
|
-
|
|
125
|
+
if self.compiler == "pgfortran":
|
|
126
|
+
compiler_options.append("-mp")
|
|
127
|
+
else:
|
|
128
|
+
compiler_options.append("-fopenmp")
|
|
126
129
|
|
|
130
|
+
#detect whether to use nvcc as default instead of g++, may overrule an explicitly passed g++
|
|
127
131
|
if ("#include <cuda" in kernel_string) or ("__global__" in kernel_string):
|
|
128
|
-
if self.nvcc_available:
|
|
132
|
+
if self.compiler == "g++" and self.nvcc_available:
|
|
129
133
|
self.compiler = "nvcc"
|
|
130
134
|
|
|
135
|
+
#select right suffix based on compiler
|
|
136
|
+
suffix = ".cc"
|
|
137
|
+
if self.compiler in ["gfortran", "pgfortran", "ftn", "ifort"]:
|
|
138
|
+
suffix = ".F90"
|
|
131
139
|
if self.compiler == "nvcc":
|
|
132
140
|
suffix = suffix[:-1] + "u"
|
|
133
141
|
compiler_options = ["-Xcompiler=" + c for c in compiler_options]
|
|
134
142
|
|
|
143
|
+
if ".c" in suffix:
|
|
144
|
+
if not "extern \"C\"" in kernel_string:
|
|
145
|
+
kernel_string = "extern \"C\" {\n" + kernel_string + "\n}"
|
|
146
|
+
|
|
147
|
+
#copy user specified compiler options to current list
|
|
135
148
|
if self.compiler_options:
|
|
136
149
|
compiler_options += self.compiler_options
|
|
137
150
|
|
|
@@ -146,6 +159,17 @@ class CFunctions(object):
|
|
|
146
159
|
source_file = get_temp_filename(suffix=suffix)
|
|
147
160
|
filename = ".".join(source_file.split(".")[:-1])
|
|
148
161
|
|
|
162
|
+
#detect Fortran modules
|
|
163
|
+
match = re.search(r"\s*module\s+([a-zA-Z_]*)", kernel_string)
|
|
164
|
+
if match:
|
|
165
|
+
if self.compiler == "gfortran":
|
|
166
|
+
kernel_name = "__" + match.group(1) + "_MOD_" + kernel_name
|
|
167
|
+
elif self.compiler in ["ftn", "ifort"]:
|
|
168
|
+
kernel_name = match.group(1) + "_mp_" + kernel_name + "_"
|
|
169
|
+
elif self.compiler == "pgfortran":
|
|
170
|
+
kernel_name = match.group(1) + "_" + kernel_name + "_"
|
|
171
|
+
|
|
172
|
+
|
|
149
173
|
try:
|
|
150
174
|
write_file(source_file, kernel_string)
|
|
151
175
|
|
|
@@ -156,8 +180,8 @@ class CFunctions(object):
|
|
|
156
180
|
subprocess.check_call([self.compiler, "-c", source_file] + compiler_options + ["-o", filename + ".o"])
|
|
157
181
|
subprocess.check_call([self.compiler, filename + ".o"] + compiler_options + ["-shared", "-o", filename + lib_extension] + lib_args)
|
|
158
182
|
|
|
159
|
-
self.lib = numpy.ctypeslib.load_library(filename, '.')
|
|
160
183
|
|
|
184
|
+
self.lib = numpy.ctypeslib.load_library(filename, '.')
|
|
161
185
|
func = getattr(self.lib, kernel_name)
|
|
162
186
|
func.restype = C.c_float
|
|
163
187
|
|
|
@@ -167,9 +191,9 @@ class CFunctions(object):
|
|
|
167
191
|
delete_temp_file(filename+".so")
|
|
168
192
|
delete_temp_file(filename+".dylib")
|
|
169
193
|
|
|
170
|
-
|
|
171
194
|
return func
|
|
172
195
|
|
|
196
|
+
|
|
173
197
|
def benchmark(self, func, c_args, threads, grid, times):
|
|
174
198
|
"""runs the kernel repeatedly, returns averaged returned value
|
|
175
199
|
|
|
@@ -287,7 +311,8 @@ class CFunctions(object):
|
|
|
287
311
|
:param src: A ctypes pointer to some memory allocation
|
|
288
312
|
:type src: ctypes.pointer
|
|
289
313
|
"""
|
|
290
|
-
|
|
314
|
+
arginfo = self.arg_mapping[str(src)]
|
|
315
|
+
dest[:] = numpy.ctypeslib.as_array(src, shape=arginfo.shape)
|
|
291
316
|
|
|
292
317
|
|
|
293
318
|
def cleanup_lib(self):
|
|
@@ -47,11 +47,22 @@ class CudaFunctions(object):
|
|
|
47
47
|
#inspect device properties
|
|
48
48
|
devprops = {str(k): v for (k, v) in self.context.get_device().get_attributes().items()}
|
|
49
49
|
self.max_threads = devprops['MAX_THREADS_PER_BLOCK']
|
|
50
|
-
|
|
50
|
+
cc = str(devprops.get('COMPUTE_CAPABILITY_MAJOR', '0')) + str(devprops.get('COMPUTE_CAPABILITY_MINOR', '0'))
|
|
51
|
+
if cc == "00":
|
|
52
|
+
cc = self.context.get_device().compute_capability()
|
|
53
|
+
self.cc = str(cc[0])+str(cc[1])
|
|
51
54
|
self.iterations = iterations
|
|
52
55
|
self.current_module = None
|
|
53
56
|
self.compiler_options = compiler_options or []
|
|
54
57
|
|
|
58
|
+
#select PyCUDA source module
|
|
59
|
+
if int(self.cc) >= 35:
|
|
60
|
+
self.source_mod = DynamicSourceModule
|
|
61
|
+
else:
|
|
62
|
+
self.source_mod = SourceModule
|
|
63
|
+
if not self.source_mod:
|
|
64
|
+
raise ImportError("Error: pycuda not correctly installed, please ensure pycuda is installed on the same CUDA installation as you're using right now")
|
|
65
|
+
|
|
55
66
|
#collect environment information
|
|
56
67
|
env = dict()
|
|
57
68
|
env["device_name"] = self.context.get_device().name()
|
|
@@ -114,16 +125,10 @@ class CudaFunctions(object):
|
|
|
114
125
|
if self.compiler_options:
|
|
115
126
|
compiler_options += self.compiler_options
|
|
116
127
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
self.current_module = source_mod(kernel_string, options=compiler_options + ["-e", kernel_name],
|
|
123
|
-
arch=('compute_' + self.cc) if self.cc != "00" else None,
|
|
124
|
-
code=('sm_' + self.cc) if self.cc != "00" else None,
|
|
125
|
-
cache_dir=False, no_extern_c=no_extern_c)
|
|
126
|
-
|
|
128
|
+
self.current_module = self.source_mod(kernel_string, options=compiler_options + ["-e", kernel_name],
|
|
129
|
+
arch=('compute_' + self.cc) if self.cc != "00" else None,
|
|
130
|
+
code=('sm_' + self.cc) if self.cc != "00" else None,
|
|
131
|
+
cache_dir=False, no_extern_c=no_extern_c)
|
|
127
132
|
|
|
128
133
|
func = self.current_module.get_function(kernel_name)
|
|
129
134
|
return func
|
|
@@ -35,7 +35,7 @@ import numpy
|
|
|
35
35
|
import kernel_tuner.util as util
|
|
36
36
|
import kernel_tuner.core as core
|
|
37
37
|
|
|
38
|
-
from kernel_tuner.strategies import brute_force, random_sample, diff_evo, minimize, basinhopping
|
|
38
|
+
from kernel_tuner.strategies import brute_force, random_sample, diff_evo, minimize, basinhopping, genetic_algorithm, pso, simulated_annealing, firefly_algorithm
|
|
39
39
|
|
|
40
40
|
class Options(OrderedDict):
|
|
41
41
|
"""read-only class for passing options around"""
|
|
@@ -194,6 +194,10 @@ _tuning_options = Options([
|
|
|
194
194
|
* "random_sample", specify: *sample_fraction*,
|
|
195
195
|
* "minimize" or "basinhopping", specify: *method*,
|
|
196
196
|
* "diff_evo", specify: *method*.
|
|
197
|
+
* "genetic_algorithm"
|
|
198
|
+
* "pso"
|
|
199
|
+
* "firefly_algorithm"
|
|
200
|
+
* "simulated_annealing"
|
|
197
201
|
|
|
198
202
|
"brute_force" is the default and iterates over the entire search
|
|
199
203
|
space.
|
|
@@ -213,6 +217,17 @@ _tuning_options = Options([
|
|
|
213
217
|
"rand2exp", "randtobest1bin", "best2bin", "rand2bin", "rand1bin".
|
|
214
218
|
The default is "best1bin".
|
|
215
219
|
|
|
220
|
+
"genetic_algorithm" implements a simple Genetic Algorithm, default
|
|
221
|
+
setting uses a population size of 20 for 100 generations.
|
|
222
|
+
|
|
223
|
+
"pso" implements Particle Swarm Optimization, using the default
|
|
224
|
+
setting of 20 particles for 100 iterations.
|
|
225
|
+
|
|
226
|
+
"firefly_algorithm" implements the Firefly Algorithm, using 20
|
|
227
|
+
fireflies for 100 iterations.
|
|
228
|
+
|
|
229
|
+
"simulated_annealing" uses Simulated Annealing.
|
|
230
|
+
|
|
216
231
|
""", "")),
|
|
217
232
|
("method", ("""Specify a method for the strategy that searches through
|
|
218
233
|
the parameter space during tuning.
|
|
@@ -324,6 +339,11 @@ def tune_kernel(kernel_name, kernel_string, problem_size, arguments,
|
|
|
324
339
|
raise ValueError("It's not possible to use both sample_fraction in combination with other strategies. " \
|
|
325
340
|
'Please set strategy=None or strategy="random_sample", when using sample_fraction')
|
|
326
341
|
|
|
342
|
+
strategy_map = {"genetic_algorithm": genetic_algorithm,
|
|
343
|
+
"pso": pso,
|
|
344
|
+
"simulated_annealing": simulated_annealing,
|
|
345
|
+
"firefly_algorithm": firefly_algorithm}
|
|
346
|
+
|
|
327
347
|
if strategy in [None, 'sample_fraction', 'brute_force']:
|
|
328
348
|
if sample_fraction:
|
|
329
349
|
use_strategy = random_sample
|
|
@@ -346,6 +366,8 @@ def tune_kernel(kernel_name, kernel_string, problem_size, arguments,
|
|
|
346
366
|
if not method in ["best1bin", "best1exp", "rand1exp", "randtobest1exp", "best2exp",
|
|
347
367
|
"rand2exp", "randtobest1bin", "best2bin", "rand2bin", "rand1bin"]:
|
|
348
368
|
raise ValueError("method option not recognized")
|
|
369
|
+
elif strategy in strategy_map.keys():
|
|
370
|
+
use_strategy = strategy_map[strategy]
|
|
349
371
|
else:
|
|
350
372
|
raise ValueError("strategy option not recognized")
|
|
351
373
|
strategy = use_strategy
|
|
@@ -474,6 +496,9 @@ def run_kernel(kernel_name, kernel_string, problem_size, arguments,
|
|
|
474
496
|
results.append(numpy.zeros_like(arg))
|
|
475
497
|
dev.memcpy_dtoh(results[-1], gpu_args[i])
|
|
476
498
|
|
|
499
|
+
#trying to make run_kernel work nicely with the Nvidia Visual Profiler
|
|
500
|
+
del dev
|
|
501
|
+
|
|
477
502
|
return results
|
|
478
503
|
|
|
479
504
|
|
|
@@ -4,7 +4,7 @@ from __future__ import print_function
|
|
|
4
4
|
from scipy.optimize import differential_evolution
|
|
5
5
|
from kernel_tuner import util
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
from kernel_tuner.strategies.minimize import get_bounds, _cost_func
|
|
8
8
|
|
|
9
9
|
def tune(runner, kernel_options, device_options, tuning_options):
|
|
10
10
|
""" Find the best performing kernel configuration in the parameter space
|
|
@@ -31,40 +31,21 @@ def tune(runner, kernel_options, device_options, tuning_options):
|
|
|
31
31
|
"""
|
|
32
32
|
|
|
33
33
|
results = []
|
|
34
|
+
cache = {}
|
|
34
35
|
|
|
36
|
+
tuning_options["scaling"] = False
|
|
35
37
|
#build a bounds array as needed for the optimizer
|
|
36
|
-
bounds =
|
|
38
|
+
bounds = get_bounds(tuning_options.tune_params)
|
|
39
|
+
|
|
40
|
+
args = (kernel_options, tuning_options, runner, results, cache)
|
|
37
41
|
|
|
38
42
|
#call the differential evolution optimizer
|
|
39
|
-
opt_result = differential_evolution(_cost_func, bounds,
|
|
40
|
-
|
|
43
|
+
opt_result = differential_evolution(_cost_func, bounds, args, maxiter=1,
|
|
44
|
+
polish=False, disp=tuning_options.verbose)
|
|
41
45
|
|
|
42
46
|
if tuning_options.verbose:
|
|
43
47
|
print(opt_result.message)
|
|
44
|
-
print('best config:', minimize.snap_to_nearest_config(opt_result.x, tuning_options.tune_params))
|
|
45
48
|
|
|
46
49
|
return results, runner.dev.get_environment()
|
|
47
50
|
|
|
48
51
|
|
|
49
|
-
|
|
50
|
-
def _cost_func(x, kernel_options, tuning_options, runner, results):
|
|
51
|
-
""" Cost function used by the differential evolution optimizer """
|
|
52
|
-
|
|
53
|
-
#snap values in x to nearest actual value for each parameter
|
|
54
|
-
params = minimize.snap_to_nearest_config(x, tuning_options.tune_params)
|
|
55
|
-
|
|
56
|
-
#check if this is a legal (non-restricted) parameter instance
|
|
57
|
-
if tuning_options.restrictions:
|
|
58
|
-
legal = util.check_restrictions(tuning_options.restrictions, params, tuning_options.tune_params.keys(), tuning_options.verbose)
|
|
59
|
-
if not legal:
|
|
60
|
-
return 1e20
|
|
61
|
-
|
|
62
|
-
#compile and benchmark this instance
|
|
63
|
-
res, _ = runner.run([params], kernel_options, tuning_options)
|
|
64
|
-
|
|
65
|
-
#append to tuning results
|
|
66
|
-
if len(res) > 0:
|
|
67
|
-
results.append(res[0])
|
|
68
|
-
return res[0]['time']
|
|
69
|
-
|
|
70
|
-
return 1e20
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
""" The strategy that uses the firefly algorithm for optimization"""
|
|
2
|
+
from __future__ import print_function
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from kernel_tuner.strategies.minimize import _cost_func, get_bounds_x0_eps
|
|
6
|
+
from kernel_tuner.strategies.pso import Particle
|
|
7
|
+
|
|
8
|
+
def tune(runner, kernel_options, device_options, tuning_options):
|
|
9
|
+
""" Find the best performing kernel configuration in the parameter space
|
|
10
|
+
|
|
11
|
+
:params runner: A runner from kernel_tuner.runners
|
|
12
|
+
:type runner: kernel_tuner.runner
|
|
13
|
+
|
|
14
|
+
:param kernel_options: A dictionary with all options for the kernel.
|
|
15
|
+
:type kernel_options: dict
|
|
16
|
+
|
|
17
|
+
:param device_options: A dictionary with all options for the device
|
|
18
|
+
on which the kernel should be tuned.
|
|
19
|
+
:type device_options: dict
|
|
20
|
+
|
|
21
|
+
:param tuning_options: A dictionary with all options regarding the tuning
|
|
22
|
+
process.
|
|
23
|
+
:type tuning_options: dict
|
|
24
|
+
|
|
25
|
+
:returns: A list of dictionaries for executed kernel configurations and their
|
|
26
|
+
execution times. And a dictionary that contains a information
|
|
27
|
+
about the hardware/software environment on which the tuning took place.
|
|
28
|
+
:rtype: list(dict()), dict()
|
|
29
|
+
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
results = []
|
|
33
|
+
cache = {}
|
|
34
|
+
|
|
35
|
+
#scale variables in x because PSO works with velocities to visit different configurations
|
|
36
|
+
tuning_options["scaling"] = True
|
|
37
|
+
|
|
38
|
+
#using this instead of get_bounds because scaling is used
|
|
39
|
+
bounds, _, _ = get_bounds_x0_eps(tuning_options)
|
|
40
|
+
|
|
41
|
+
args = (kernel_options, tuning_options, runner, results, cache)
|
|
42
|
+
|
|
43
|
+
num_particles = 20
|
|
44
|
+
maxiter = 100
|
|
45
|
+
|
|
46
|
+
#parameters needed by the Firefly Algorithm
|
|
47
|
+
B0 = 1.0
|
|
48
|
+
gamma = 1.0
|
|
49
|
+
alpha = 0.20
|
|
50
|
+
|
|
51
|
+
best_time_global = 1e20
|
|
52
|
+
best_position_global = []
|
|
53
|
+
|
|
54
|
+
# init particle swarm
|
|
55
|
+
swarm = []
|
|
56
|
+
for i in range(0, num_particles):
|
|
57
|
+
swarm.append(Firefly(bounds, args))
|
|
58
|
+
|
|
59
|
+
# compute initial intensities
|
|
60
|
+
for j in range(num_particles):
|
|
61
|
+
swarm[j].compute_intensity(_cost_func)
|
|
62
|
+
|
|
63
|
+
for c in range(maxiter):
|
|
64
|
+
if tuning_options.verbose:
|
|
65
|
+
print("start iteration ", c, "best time global", best_time_global)
|
|
66
|
+
|
|
67
|
+
# compare all to all and compute attractiveness
|
|
68
|
+
for i in range(num_particles):
|
|
69
|
+
for j in range(num_particles):
|
|
70
|
+
|
|
71
|
+
if swarm[i].intensity < swarm[j].intensity:
|
|
72
|
+
dist = swarm[i].distance_to(swarm[j])
|
|
73
|
+
beta = B0 * np.exp(-gamma * dist * dist)
|
|
74
|
+
|
|
75
|
+
swarm[i].move_towards(swarm[j], beta, alpha)
|
|
76
|
+
swarm[i].compute_intensity(_cost_func)
|
|
77
|
+
|
|
78
|
+
# update global best if needed, actually only used for printing
|
|
79
|
+
if swarm[i].time <= best_time_global:
|
|
80
|
+
best_position_global = swarm[i].position
|
|
81
|
+
best_time_global = swarm[i].time
|
|
82
|
+
|
|
83
|
+
swarm.sort(key=lambda x: x.time)
|
|
84
|
+
|
|
85
|
+
if tuning_options.verbose:
|
|
86
|
+
print('Final result:')
|
|
87
|
+
print(best_position_global)
|
|
88
|
+
print(best_time_global)
|
|
89
|
+
|
|
90
|
+
return results, runner.dev.get_environment()
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class Firefly(Particle):
|
|
94
|
+
"""Firefly object for use in the Firefly Algorithm"""
|
|
95
|
+
|
|
96
|
+
def __init__(self, bounds, args):
|
|
97
|
+
"""Create Firefly at random position within bounds"""
|
|
98
|
+
super().__init__(bounds, args)
|
|
99
|
+
self.bounds = bounds
|
|
100
|
+
self.intensity = 1 / self.time
|
|
101
|
+
|
|
102
|
+
def distance_to(self, other):
|
|
103
|
+
"""Return Euclidian distance between self and other Firefly"""
|
|
104
|
+
return np.linalg.norm(self.position-other.position)
|
|
105
|
+
|
|
106
|
+
def compute_intensity(self, _cost_func):
|
|
107
|
+
"""Evaluate cost function and compute intensity at this position"""
|
|
108
|
+
self.evaluate(_cost_func)
|
|
109
|
+
self.intensity = 1 / self.time
|
|
110
|
+
|
|
111
|
+
def move_towards(self, other, beta, alpha):
|
|
112
|
+
"""Move firefly towards another given beta and alpha values"""
|
|
113
|
+
self.position += beta * (other.position - self.position)
|
|
114
|
+
self.position += alpha * (np.random.uniform(-0.5, 0.5, len(self.position)))
|
|
115
|
+
self.position = np.minimum(self.position, [b[1] for b in self.bounds])
|
|
116
|
+
self.position = np.maximum(self.position, [b[0] for b in self.bounds])
|