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.
Files changed (41) hide show
  1. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/PKG-INFO +41 -19
  2. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/README.rst +33 -17
  3. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/c.py +57 -32
  4. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/cuda.py +16 -11
  5. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/interface.py +26 -1
  6. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/strategies/basinhopping.py +0 -1
  7. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/strategies/diff_evo.py +8 -27
  8. kernel_tuner-0.2.0/kernel_tuner/strategies/firefly_algorithm.py +116 -0
  9. kernel_tuner-0.2.0/kernel_tuner/strategies/genetic_algorithm.py +117 -0
  10. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/strategies/minimize.py +2 -4
  11. kernel_tuner-0.2.0/kernel_tuner/strategies/pso.py +113 -0
  12. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/strategies/random_sample.py +6 -2
  13. kernel_tuner-0.2.0/kernel_tuner/strategies/simulated_annealing.py +117 -0
  14. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/util.py +28 -24
  15. kernel_tuner-0.2.0/kernel_tuner/wrappers.py +121 -0
  16. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner.egg-info/PKG-INFO +41 -19
  17. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner.egg-info/SOURCES.txt +5 -0
  18. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/setup.py +1 -1
  19. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/test/test_c_functions.py +21 -2
  20. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/test/test_cuda_mocked.py +19 -11
  21. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/test/test_interface.py +3 -3
  22. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/test/test_util_functions.py +22 -37
  23. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/LICENSE +0 -0
  24. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/MANIFEST.in +0 -0
  25. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/__init__.py +0 -0
  26. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/core.py +0 -0
  27. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/opencl.py +0 -0
  28. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/runners/__init__.py +0 -0
  29. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/runners/noodles.py +0 -0
  30. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/runners/sequential.py +0 -0
  31. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/strategies/__init__.py +0 -0
  32. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner/strategies/brute_force.py +0 -0
  33. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner.egg-info/dependency_links.txt +0 -0
  34. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner.egg-info/requires.txt +0 -0
  35. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/kernel_tuner.egg-info/top_level.txt +0 -0
  36. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/setup.cfg +0 -0
  37. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/test/test_cuda_functions.py +0 -0
  38. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/test/test_device_interface.py +0 -0
  39. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/test/test_minimize.py +0 -0
  40. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/test/test_opencl_functions.py +0 -0
  41. {kernel_tuner-0.1.8 → kernel_tuner-0.2.0}/test/test_runners.py +0 -0
@@ -1,15 +1,15 @@
1
- Metadata-Version: 1.1
1
+ Metadata-Version: 2.1
2
2
  Name: kernel_tuner
3
- Version: 0.1.8
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: A simple CUDA/OpenCL Auto-Tuner in Python
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 the Kernel Tuner is in preparation, in the meantime please cite the Kernel Tuner as follows:
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
- @misc{
148
- author = {Ben van Werkhoven},
149
- title = {Kernel Tuner: A simple CUDA/OpenCL Auto-Tuner in Python},
150
- year = {2018}
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 and supports
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: A simple CUDA/OpenCL Auto-Tuner in Python
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 the Kernel Tuner is in preparation, in the meantime please cite the Kernel Tuner as follows:
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
- @misc{
140
- author = {Ben van Werkhoven},
141
- title = {Kernel Tuner: A simple CUDA/OpenCL Auto-Tuner in Python},
142
- year = {2018}
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 and supports
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
- dtype_map = {"int32": C.c_int32,
73
- "int64": C.c_int64,
74
- "float32": C.c_float,
75
- "float64": C.c_double}
76
- np_to_c_type_map = {numpy.int32: C.c_int32,
77
- numpy.int64: C.c_int64,
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.append(arg.ctypes.data_as(C.POINTER(dtype_map[dtype_str])))
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[-1])] = arg.shape
89
- elif isinstance(arg, tuple(np_to_c_type_map.keys())):
90
- ctype_args.append(np_to_c_type_map[type(arg)](arg))
91
- self.arg_mapping[str(ctype_args[-1])] = ()
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
- if "#include <omp.h>" in kernel_string:
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
- compiler_options.append("-fopenmp")
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
- dest[:] = numpy.ctypeslib.as_array(src, shape=self.arg_mapping[str(src)])
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
- self.cc = str(devprops.get('COMPUTE_CAPABILITY_MAJOR','0')) + str(devprops.get('COMPUTE_CAPABILITY_MINOR','0'))
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
- if int(self.cc) >= 35:
118
- source_mod = DynamicSourceModule
119
- else:
120
- source_mod = SourceModule
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
 
@@ -55,4 +55,3 @@ def tune(runner, kernel_options, device_options, tuning_options):
55
55
  print(opt_result.message)
56
56
 
57
57
  return results, runner.dev.get_environment()
58
-
@@ -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
- import kernel_tuner.strategies.minimize as minimize
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 = minimize.get_bounds(tuning_options.tune_params)
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, [kernel_options, tuning_options, runner, results],
40
- maxiter=1, polish=False, disp=tuning_options.verbose)
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])