kernel-tuner 0.1.2__tar.gz → 0.1.4__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 (31) hide show
  1. {kernel_tuner-0.1.2 → kernel_tuner-0.1.4}/PKG-INFO +50 -81
  2. {kernel_tuner-0.1.2 → kernel_tuner-0.1.4}/README.rst +49 -80
  3. {kernel_tuner-0.1.2 → kernel_tuner-0.1.4}/kernel_tuner/c.py +90 -45
  4. kernel_tuner-0.1.4/kernel_tuner/core.py +198 -0
  5. {kernel_tuner-0.1.2 → kernel_tuner-0.1.4}/kernel_tuner/cuda.py +22 -9
  6. {kernel_tuner-0.1.2 → kernel_tuner-0.1.4}/kernel_tuner/interface.py +61 -51
  7. {kernel_tuner-0.1.2 → kernel_tuner-0.1.4}/kernel_tuner/opencl.py +20 -3
  8. {kernel_tuner-0.1.2 → kernel_tuner-0.1.4}/kernel_tuner/runners/random_sample.py +12 -17
  9. {kernel_tuner-0.1.2 → kernel_tuner-0.1.4}/kernel_tuner/runners/sequential_brute_force.py +11 -17
  10. {kernel_tuner-0.1.2 → kernel_tuner-0.1.4}/kernel_tuner/util.py +47 -44
  11. {kernel_tuner-0.1.2 → kernel_tuner-0.1.4}/kernel_tuner.egg-info/PKG-INFO +50 -81
  12. {kernel_tuner-0.1.2 → kernel_tuner-0.1.4}/kernel_tuner.egg-info/SOURCES.txt +1 -0
  13. kernel_tuner-0.1.4/kernel_tuner.egg-info/requires.txt +1 -0
  14. kernel_tuner-0.1.4/requirements.txt +1 -0
  15. {kernel_tuner-0.1.2 → kernel_tuner-0.1.4}/setup.py +6 -1
  16. {kernel_tuner-0.1.2 → kernel_tuner-0.1.4}/test/test_c_functions.py +13 -10
  17. {kernel_tuner-0.1.2 → kernel_tuner-0.1.4}/test/test_cuda_mocked.py +3 -3
  18. {kernel_tuner-0.1.2 → kernel_tuner-0.1.4}/test/test_interface.py +13 -8
  19. {kernel_tuner-0.1.2 → kernel_tuner-0.1.4}/test/test_kernel_tuner.py +12 -16
  20. {kernel_tuner-0.1.2 → kernel_tuner-0.1.4}/test/test_runners.py +1 -1
  21. kernel_tuner-0.1.2/kernel_tuner/core.py +0 -158
  22. kernel_tuner-0.1.2/requirements.txt +0 -7
  23. {kernel_tuner-0.1.2 → kernel_tuner-0.1.4}/LICENSE +0 -0
  24. {kernel_tuner-0.1.2 → kernel_tuner-0.1.4}/MANIFEST.in +0 -0
  25. {kernel_tuner-0.1.2 → kernel_tuner-0.1.4}/kernel_tuner/__init__.py +0 -0
  26. {kernel_tuner-0.1.2 → kernel_tuner-0.1.4}/kernel_tuner/runners/__init__.py +0 -0
  27. {kernel_tuner-0.1.2 → kernel_tuner-0.1.4}/kernel_tuner.egg-info/dependency_links.txt +0 -0
  28. {kernel_tuner-0.1.2 → kernel_tuner-0.1.4}/kernel_tuner.egg-info/top_level.txt +0 -0
  29. {kernel_tuner-0.1.2 → kernel_tuner-0.1.4}/setup.cfg +0 -0
  30. {kernel_tuner-0.1.2 → kernel_tuner-0.1.4}/test/test_cuda_functions.py +0 -0
  31. {kernel_tuner-0.1.2 → kernel_tuner-0.1.4}/test/test_opencl_functions.py +0 -0
@@ -1,20 +1,19 @@
1
1
  Metadata-Version: 1.1
2
2
  Name: kernel_tuner
3
- Version: 0.1.2
3
+ Version: 0.1.4
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: A simple CUDA/OpenCL kernel tuner in Python
10
- ===========================================
9
+ Description: Kernel Tuner: A simple CUDA/OpenCL kernel tuner in Python
10
+ =========================================================
11
11
 
12
12
  |Build Status| |Codacy Badge| |Codacy Badge2|
13
13
 
14
- The goal of this project is to provide a - as simple as possible - tool
15
- for tuning CUDA and OpenCL kernels. This implies that any CUDA or OpenCL
16
- kernel can be tuned without requiring extensive changes to the original
17
- kernel code.
14
+ The Kernel Tuner is a - as simple as possible - tool for testing and auto-tuning
15
+ CUDA and OpenCL kernels. This means that any CUDA or OpenCL kernel can be tuned
16
+ without requiring extensive changes to the original kernel code.
18
17
 
19
18
  A very common problem in GPU programming is that some combination of
20
19
  thread block dimensions and other kernel parameters, like tiling or
@@ -22,18 +21,16 @@ Description: A simple CUDA/OpenCL kernel tuner in Python
22
21
  kernel configurations. The goal of auto-tuning is to automate the
23
22
  process of finding the best performing configuration for a given device.
24
23
 
25
- This kernel tuner aims that you can directly use the tuned kernel
26
- without introducing any new dependencies. The tuned kernels can
27
- afterwards be used independently of the programming environment, whether
28
- that is using C/C++/Java/Fortran or Python doesn't matter.
24
+ The Kernel Tuner offers two main functions which are called run\_kernel and
25
+ tune\_kernel. With run\_kernel it's very easy to write unit tests for your GPU
26
+ kernels in Python. With tune\_kernel you can auto-tune your kernels using only a
27
+ simple Python script. These functions are very flexible and come with a lot of
28
+ optional parameters, for a complete list see the `documentation website
29
+ <http://benvanwerkhoven.github.io/kernel_tuner/user-api.html>`__.
29
30
 
30
- The kernel\_tuner module currently only contains main one function which
31
- is called tune\_kernel to which you pass at least the kernel name, a
32
- string containing the kernel code, the problem size, a list of kernel
33
- function arguments, and a dictionary of tunable parameters. There are
34
- also a lot of optional parameters, for a complete list see the full
35
- documentation of
36
- `tune\_kernel <http://benvanwerkhoven.github.io/kernel_tuner/details.html>`__.
31
+ The Kernel Tuner does not introduce any new dependencies in your kernels. The
32
+ tuned kernels can afterwards be used independently of the programming environment,
33
+ whether that is using C/C++/Java/Fortran or Python doesn't matter.
37
34
 
38
35
  Documentation
39
36
  -------------
@@ -44,41 +41,35 @@ Description: A simple CUDA/OpenCL kernel tuner in Python
44
41
  Installation
45
42
  ------------
46
43
 
47
- To install from PyPi:
44
+ The easiest way to install the Kernel Tuner is using pip:
48
45
 
49
- - ``pip install kernel_tuner``
46
+ .. code-block:: bash
50
47
 
51
- To install from the source (and get the tutorial and examples):
48
+ pip install kernel_tuner
52
49
 
53
- - clone the repository
54
-
55
- - With a GitHub account: ``git clone git@github.com:benvanwerkhoven/kernel_tuner.git``
56
- - Without GitHub account: ``git clone https://github.com/benvanwerkhoven/kernel_tuner.git``
57
-
58
- - change into the top-level directory
50
+ But you can also install from the git repository. This way you also get the
51
+ examples and the tutorials:
59
52
 
60
- - ``cd kernel_tuner``
61
-
62
- - install using
63
-
64
- - ``pip install .``
53
+ .. code-block:: bash
65
54
 
66
- Dependencies
67
- ------------
68
- Python 2.7 or Python 3.5
69
-
70
- PyCuda and/or PyOpenCL (https://mathema.tician.de/software/)
71
-
72
- - To tune CUDA kernels
55
+ git clone https://github.com/benvanwerkhoven/kernel_tuner.git
56
+ cd kernel_tuner
57
+ pip install .
58
+
59
+ To tune CUDA kernels:
73
60
 
74
- - Make sure you have the `CUDA Toolkit <https://developer.nvidia.com/cuda-toolkit>`_ installed
75
- - You can install PyCuda using ``pip install pycuda``
61
+ - First, make sure you have the `CUDA Toolkit <https://developer.nvidia.com/cuda-toolkit>`_ installed
62
+ - You can install PyCuda using ``pip install pycuda``
76
63
 
77
- - To tune OpenCL kernels
64
+ To tune OpenCL kernels:
78
65
 
79
- - Make sure you have an OpenCL compiler for your intended OpenCL platform
66
+ - First, make sure you have an OpenCL compiler for your intended OpenCL platform
80
67
  - You can install PyOpenCL using ``pip install pyopencl``
81
68
 
69
+ If you need more information about how to install the Kernel Tuner and all
70
+ dependencies see the `installation guide
71
+ <http://benvanwerkhoven.github.io/kernel_tuner/install.html>`__
72
+
82
73
  Example usage
83
74
  -------------
84
75
 
@@ -104,7 +95,7 @@ Description: A simple CUDA/OpenCL kernel tuner in Python
104
95
  args = [c, a, b, n]
105
96
 
106
97
  tune_params = dict()
107
- tune_params["block_size_x"] = [128+64*i for i in range(15)]
98
+ tune_params["block_size_x"] = [32, 64, 128, 256, 512]
108
99
 
109
100
  tune_kernel("vector_add", kernel_string, size, args, tune_params)
110
101
 
@@ -121,22 +112,23 @@ Description: A simple CUDA/OpenCL kernel tuner in Python
121
112
  }
122
113
  """
123
114
 
124
- Or even just a C function, see the example
125
- `here <https://github.com/benvanwerkhoven/kernel_tuner/blob/master/examples/c/vector_add.py>`__.
126
-
127
- You can find these and many - more extensive - example codes, in the
128
- `examples <https://github.com/benvanwerkhoven/kernel_tuner/blob/master/examples/>`__
129
- directory.
115
+ The Kernel Tuner will detect the kernel language and select the right compiler and
116
+ runtime. For every kernel in the parameter space, the Kernel Tuner will insert C
117
+ preprocessor defines for the tunable parameters, compile, and benchmark the kernel. The
118
+ timing results will be printed to the console, but are also returned by tune_kernel to
119
+ allow further analysis. Note that this is just the default behavior, what and how
120
+ tune_kernel does exactly is controlled through its many `optional arguments
121
+ <http://benvanwerkhoven.github.io/kernel_tuner/user-api.html#kernel_tuner.tune_kernel>`__.
130
122
 
131
- See the `full
132
- documentation <http://benvanwerkhoven.github.io/kernel_tuner/index.html>`__
133
- for several highly detailed tutorial-style explanations of example
134
- kernels and the scripts to tune them.
123
+ You can find many - more extensive - example codes, in the
124
+ `examples directory <https://github.com/benvanwerkhoven/kernel_tuner/blob/master/examples/>`__
125
+ and in the `Kernel Tuner
126
+ documentation pages <http://benvanwerkhoven.github.io/kernel_tuner/index.html>`__.
135
127
 
136
128
  Tuning host and kernel code
137
129
  ---------------------------
138
130
 
139
- It is also possible to tune for combinations of tunable parameters in
131
+ It is possible to tune for combinations of tunable parameters in
140
132
  both host and kernel code. This allows for a number of powerfull things,
141
133
  such as tuning the number of streams for a kernel that uses CUDA Streams
142
134
  or OpenCL Command Queues to overlap transfers between host and device
@@ -160,33 +152,10 @@ Description: A simple CUDA/OpenCL kernel tuner in Python
160
152
  answer = [a+b, None, None] # the order matches the arguments (in args) to the kernel
161
153
  tune_kernel("vector_add", kernel_string, size, args, tune_params, answer=answer)
162
154
 
163
- Contribution guide
164
- ------------------
165
-
166
- The kernel tuner follows the Google Python style guide, with Sphinxdoc
167
- docstrings for module public functions. If you want to contribute to the
168
- project please fork it, create a branch including your addition, and
169
- create a pull request.
170
-
171
- The tests use relative imports and can be run directly after making
172
- changes to the code. To run all tests use ``nosetests`` in the main
173
- directory. To run the examples after code changes, you need to run
174
- ``pip install --upgrade .`` in the main directory. Documentation is
175
- generated by typing ``make html`` in the doc directory, the contents of
176
- ``doc/build/html/`` should then be copied to ``sphinxdoc`` directory of
177
- the ``gh-pages`` branch.
178
-
179
- Before creating a pull request please ensure the following:
180
-
181
- * You have written unit tests to test your additions and all unit tests pass
182
- * The examples still work and produce the same (or better) results
183
- * The code is compatible with both Python 2.7 and Python 3.5
184
- * An entry about the change or addition is created in CHANGELOG.md
185
-
186
- Contributing authors so far:
155
+ Contributing
156
+ ------------
187
157
 
188
- * Ben van Werkhoven
189
- * Berend Weel
158
+ Please see the `Contributions Guide <http://benvanwerkhoven.github.io/kernel_tuner/contributing.html>`__.
190
159
 
191
160
  Citation
192
161
  --------
@@ -1,12 +1,11 @@
1
- A simple CUDA/OpenCL kernel tuner in Python
2
- ===========================================
1
+ Kernel Tuner: A simple CUDA/OpenCL kernel tuner in Python
2
+ =========================================================
3
3
 
4
4
  |Build Status| |Codacy Badge| |Codacy Badge2|
5
5
 
6
- The goal of this project is to provide a - as simple as possible - tool
7
- for tuning CUDA and OpenCL kernels. This implies that any CUDA or OpenCL
8
- kernel can be tuned without requiring extensive changes to the original
9
- kernel code.
6
+ The Kernel Tuner is a - as simple as possible - tool for testing and auto-tuning
7
+ CUDA and OpenCL kernels. This means that any CUDA or OpenCL kernel can be tuned
8
+ without requiring extensive changes to the original kernel code.
10
9
 
11
10
  A very common problem in GPU programming is that some combination of
12
11
  thread block dimensions and other kernel parameters, like tiling or
@@ -14,18 +13,16 @@ unrolling factors, results in dramatically better performance than other
14
13
  kernel configurations. The goal of auto-tuning is to automate the
15
14
  process of finding the best performing configuration for a given device.
16
15
 
17
- This kernel tuner aims that you can directly use the tuned kernel
18
- without introducing any new dependencies. The tuned kernels can
19
- afterwards be used independently of the programming environment, whether
20
- that is using C/C++/Java/Fortran or Python doesn't matter.
16
+ The Kernel Tuner offers two main functions which are called run\_kernel and
17
+ tune\_kernel. With run\_kernel it's very easy to write unit tests for your GPU
18
+ kernels in Python. With tune\_kernel you can auto-tune your kernels using only a
19
+ simple Python script. These functions are very flexible and come with a lot of
20
+ optional parameters, for a complete list see the `documentation website
21
+ <http://benvanwerkhoven.github.io/kernel_tuner/user-api.html>`__.
21
22
 
22
- The kernel\_tuner module currently only contains main one function which
23
- is called tune\_kernel to which you pass at least the kernel name, a
24
- string containing the kernel code, the problem size, a list of kernel
25
- function arguments, and a dictionary of tunable parameters. There are
26
- also a lot of optional parameters, for a complete list see the full
27
- documentation of
28
- `tune\_kernel <http://benvanwerkhoven.github.io/kernel_tuner/details.html>`__.
23
+ The Kernel Tuner does not introduce any new dependencies in your kernels. The
24
+ tuned kernels can afterwards be used independently of the programming environment,
25
+ whether that is using C/C++/Java/Fortran or Python doesn't matter.
29
26
 
30
27
  Documentation
31
28
  -------------
@@ -36,41 +33,35 @@ The full documentation is available
36
33
  Installation
37
34
  ------------
38
35
 
39
- To install from PyPi:
36
+ The easiest way to install the Kernel Tuner is using pip:
40
37
 
41
- - ``pip install kernel_tuner``
38
+ .. code-block:: bash
42
39
 
43
- To install from the source (and get the tutorial and examples):
40
+ pip install kernel_tuner
44
41
 
45
- - clone the repository
46
-
47
- - With a GitHub account: ``git clone git@github.com:benvanwerkhoven/kernel_tuner.git``
48
- - Without GitHub account: ``git clone https://github.com/benvanwerkhoven/kernel_tuner.git``
49
-
50
- - change into the top-level directory
42
+ But you can also install from the git repository. This way you also get the
43
+ examples and the tutorials:
51
44
 
52
- - ``cd kernel_tuner``
53
-
54
- - install using
55
-
56
- - ``pip install .``
45
+ .. code-block:: bash
57
46
 
58
- Dependencies
59
- ------------
60
- Python 2.7 or Python 3.5
61
-
62
- PyCuda and/or PyOpenCL (https://mathema.tician.de/software/)
63
-
64
- - To tune CUDA kernels
47
+ git clone https://github.com/benvanwerkhoven/kernel_tuner.git
48
+ cd kernel_tuner
49
+ pip install .
50
+
51
+ To tune CUDA kernels:
65
52
 
66
- - Make sure you have the `CUDA Toolkit <https://developer.nvidia.com/cuda-toolkit>`_ installed
67
- - You can install PyCuda using ``pip install pycuda``
53
+ - First, make sure you have the `CUDA Toolkit <https://developer.nvidia.com/cuda-toolkit>`_ installed
54
+ - You can install PyCuda using ``pip install pycuda``
68
55
 
69
- - To tune OpenCL kernels
56
+ To tune OpenCL kernels:
70
57
 
71
- - Make sure you have an OpenCL compiler for your intended OpenCL platform
58
+ - First, make sure you have an OpenCL compiler for your intended OpenCL platform
72
59
  - You can install PyOpenCL using ``pip install pyopencl``
73
60
 
61
+ If you need more information about how to install the Kernel Tuner and all
62
+ dependencies see the `installation guide
63
+ <http://benvanwerkhoven.github.io/kernel_tuner/install.html>`__
64
+
74
65
  Example usage
75
66
  -------------
76
67
 
@@ -96,7 +87,7 @@ The following shows a simple example for tuning a CUDA kernel:
96
87
  args = [c, a, b, n]
97
88
 
98
89
  tune_params = dict()
99
- tune_params["block_size_x"] = [128+64*i for i in range(15)]
90
+ tune_params["block_size_x"] = [32, 64, 128, 256, 512]
100
91
 
101
92
  tune_kernel("vector_add", kernel_string, size, args, tune_params)
102
93
 
@@ -113,22 +104,23 @@ The exact same Python code can be used to tune an OpenCL kernel:
113
104
  }
114
105
  """
115
106
 
116
- Or even just a C function, see the example
117
- `here <https://github.com/benvanwerkhoven/kernel_tuner/blob/master/examples/c/vector_add.py>`__.
118
-
119
- You can find these and many - more extensive - example codes, in the
120
- `examples <https://github.com/benvanwerkhoven/kernel_tuner/blob/master/examples/>`__
121
- directory.
107
+ The Kernel Tuner will detect the kernel language and select the right compiler and
108
+ runtime. For every kernel in the parameter space, the Kernel Tuner will insert C
109
+ preprocessor defines for the tunable parameters, compile, and benchmark the kernel. The
110
+ timing results will be printed to the console, but are also returned by tune_kernel to
111
+ allow further analysis. Note that this is just the default behavior, what and how
112
+ tune_kernel does exactly is controlled through its many `optional arguments
113
+ <http://benvanwerkhoven.github.io/kernel_tuner/user-api.html#kernel_tuner.tune_kernel>`__.
122
114
 
123
- See the `full
124
- documentation <http://benvanwerkhoven.github.io/kernel_tuner/index.html>`__
125
- for several highly detailed tutorial-style explanations of example
126
- kernels and the scripts to tune them.
115
+ You can find many - more extensive - example codes, in the
116
+ `examples directory <https://github.com/benvanwerkhoven/kernel_tuner/blob/master/examples/>`__
117
+ and in the `Kernel Tuner
118
+ documentation pages <http://benvanwerkhoven.github.io/kernel_tuner/index.html>`__.
127
119
 
128
120
  Tuning host and kernel code
129
121
  ---------------------------
130
122
 
131
- It is also possible to tune for combinations of tunable parameters in
123
+ It is possible to tune for combinations of tunable parameters in
132
124
  both host and kernel code. This allows for a number of powerfull things,
133
125
  such as tuning the number of streams for a kernel that uses CUDA Streams
134
126
  or OpenCL Command Queues to overlap transfers between host and device
@@ -152,33 +144,10 @@ expected output of the kernel. Input arguments are replaced with None.
152
144
  answer = [a+b, None, None] # the order matches the arguments (in args) to the kernel
153
145
  tune_kernel("vector_add", kernel_string, size, args, tune_params, answer=answer)
154
146
 
155
- Contribution guide
156
- ------------------
157
-
158
- The kernel tuner follows the Google Python style guide, with Sphinxdoc
159
- docstrings for module public functions. If you want to contribute to the
160
- project please fork it, create a branch including your addition, and
161
- create a pull request.
162
-
163
- The tests use relative imports and can be run directly after making
164
- changes to the code. To run all tests use ``nosetests`` in the main
165
- directory. To run the examples after code changes, you need to run
166
- ``pip install --upgrade .`` in the main directory. Documentation is
167
- generated by typing ``make html`` in the doc directory, the contents of
168
- ``doc/build/html/`` should then be copied to ``sphinxdoc`` directory of
169
- the ``gh-pages`` branch.
170
-
171
- Before creating a pull request please ensure the following:
172
-
173
- * You have written unit tests to test your additions and all unit tests pass
174
- * The examples still work and produce the same (or better) results
175
- * The code is compatible with both Python 2.7 and Python 3.5
176
- * An entry about the change or addition is created in CHANGELOG.md
177
-
178
- Contributing authors so far:
147
+ Contributing
148
+ ------------
179
149
 
180
- * Ben van Werkhoven
181
- * Berend Weel
150
+ Please see the `Contributions Guide <http://benvanwerkhoven.github.io/kernel_tuner/contributing.html>`__.
182
151
 
183
152
  Citation
184
153
  --------
@@ -1,16 +1,17 @@
1
1
  """ This module contains the functionality for running and compiling C functions """
2
2
 
3
- import numpy
4
- import ctypes as C
5
- import _ctypes
6
3
  import subprocess
7
- import os
4
+ import platform
8
5
  import errno
6
+ import logging
7
+ import ctypes as C
8
+ import _ctypes
9
9
 
10
+ import numpy
10
11
  import numpy.ctypeslib
11
- from kernel_tuner.util import get_temp_filename, delete_temp_file
12
12
 
13
- import logging
13
+ from kernel_tuner.util import get_temp_filename, delete_temp_file, write_file
14
+
14
15
 
15
16
  class CFunctions(object):
16
17
  """Class that groups the code for running and compiling C functions"""
@@ -21,20 +22,46 @@ class CFunctions(object):
21
22
  :param iterations: Number of iterations used while benchmarking a kernel, 7 by default.
22
23
  :type iterations: int
23
24
  """
24
- self.ITERATIONS = iterations
25
+ self.iterations = iterations
25
26
  self.max_threads = 1024
26
27
  self.compiler_options = compiler_options
27
28
  self.lib = None
29
+ self.using_openmp = False
30
+ self.arg_mapping = dict()
28
31
 
29
- #test if nvcc is available, otherwise use gcc
30
- self.compiler = "nvcc"
32
+ #use gcc by default
33
+ self.compiler = "g++"
31
34
  try:
32
- subprocess.check_call([self.compiler, "--version"], stdout=open(os.devnull, 'w'))
35
+ gcc_version = str(subprocess.check_output([self.compiler, "--version"]))
36
+ gcc_version = gcc_version.splitlines()[0].split(" ")[-1]
37
+ except OSError as e:
38
+ raise e
39
+
40
+ #check if nvcc is available
41
+ self.nvcc_available = False
42
+ try:
43
+ nvcc_version = str(subprocess.check_output(["nvcc", "--version"]))
44
+ nvcc_version = nvcc_version.splitlines()[-1].split(" ")[-1]
45
+ self.nvcc_available = True
33
46
  except OSError as e:
34
- self.compiler = "gcc"
35
47
  if e.errno != errno.ENOENT:
36
48
  raise e
37
49
 
50
+ #environment info
51
+ env = dict()
52
+ env["GCC Version"] = gcc_version
53
+ if self.nvcc_available:
54
+ env["NVCC Version"] = nvcc_version
55
+ env["iterations"] = self.iterations
56
+ env["compiler_options"] = compiler_options
57
+ self.env = env
58
+ self.name = platform.processor()
59
+
60
+ def get_environment(self):
61
+ """Return dictionary with information about the environment"""
62
+ return self.env
63
+
64
+
38
65
  def ready_argument_list(self, arguments):
39
66
  """ready argument list to be passed to the C function
40
67
 
@@ -46,31 +73,30 @@ class CFunctions(object):
46
73
  :returns: A list of arguments that can be passed to the C function.
47
74
  :rtype: list()
48
75
  """
49
- self.arg_mapping = dict()
50
76
  ctype_args = []
77
+
78
+ dtype_map = {"int32": C.c_int32,
79
+ "int64": C.c_int64,
80
+ "float32": C.c_float,
81
+ "float64": C.c_double}
82
+ np_to_c_type_map = {numpy.int32: C.c_int32,
83
+ numpy.int64: C.c_int64,
84
+ numpy.float32: C.c_float,
85
+ numpy.float64: C.c_double}
86
+
51
87
  for arg in arguments:
52
88
  if isinstance(arg, numpy.ndarray):
53
- if arg.dtype == 'float32':
54
- ctype_args.append(arg.ctypes.data_as(C.POINTER(C.c_float)))
55
- elif arg.dtype == 'float64':
56
- ctype_args.append(arg.ctypes.data_as(C.POINTER(C.c_double)))
57
- elif arg.dtype == 'int32':
58
- ctype_args.append(arg.ctypes.data_as(C.POINTER(C.c_int)))
89
+ dtype_str = str(arg.dtype)
90
+ if dtype_str in dtype_map.keys():
91
+ ctype_args.append(arg.ctypes.data_as(C.POINTER(dtype_map[dtype_str])))
59
92
  else:
60
93
  raise TypeError("unknown dtype for ndarray")
61
94
  self.arg_mapping[str(ctype_args[-1])] = arg.shape
62
- elif numpy.isscalar(arg):
63
- if hasattr(arg, 'dtype'):
64
- if str(arg.dtype).startswith('int'):
65
- ctype_args.append(int(arg))
66
- elif str(arg.dtype).startswith('float'):
67
- ctype_args.append(float(arg))
68
- else:
69
- raise TypeError("Argument is scalar with a dtype, but does not start with int or float")
70
- else:
71
- ctype_args.append(arg)
95
+ elif isinstance(arg, tuple(np_to_c_type_map.keys())):
96
+ ctype_args.append(np_to_c_type_map[type(arg)](arg))
97
+ self.arg_mapping[str(ctype_args[-1])] = ()
72
98
  else:
73
- raise TypeError("Argument is not a numpy.ndarray and is not a scalar %s" % type(arg))
99
+ raise TypeError("Argument is not numpy ndarray or numpy scalar %s" % type(arg))
74
100
 
75
101
  return ctype_args
76
102
 
@@ -95,12 +121,20 @@ class CFunctions(object):
95
121
 
96
122
  filename = get_temp_filename()
97
123
  source_file = filename+".cc"
98
- kernel_string = "extern \"C\" {\n" + kernel_string + "\n}"
124
+
125
+ if not "extern \"C\"" in kernel_string:
126
+ kernel_string = "extern \"C\" {\n" + kernel_string + "\n}"
99
127
 
100
128
  compiler_options = ["-fPIC"]
101
129
  if "#include <omp.h>" in kernel_string:
130
+ logging.debug('set using_openmp to true')
131
+ self.using_openmp = True
102
132
  compiler_options.append("-fopenmp")
103
133
 
134
+ if ("#include <cuda" in kernel_string) or ("__global__" in kernel_string):
135
+ if self.nvcc_available:
136
+ self.compiler = "nvcc"
137
+
104
138
  if self.compiler == "nvcc":
105
139
  source_file = source_file[:-1] + "u"
106
140
  compiler_options = ["-Xcompiler=" + c for c in compiler_options]
@@ -112,12 +146,15 @@ class CFunctions(object):
112
146
  if "CL/cl.h" in kernel_string:
113
147
  lib_args = ["-lOpenCL"]
114
148
 
149
+ logging.debug('using compiler ' + self.compiler)
150
+ logging.debug('compiler_options ' + " ".join(compiler_options))
151
+ logging.debug('lib_args ' + " ".join(lib_args))
152
+
115
153
  try:
116
- with open(source_file, 'w') as f:
117
- f.write(kernel_string)
154
+ write_file(source_file, kernel_string)
118
155
 
119
156
  subprocess.check_call([self.compiler, "-c", source_file] + compiler_options + ["-o", filename+".o"])
120
- subprocess.check_call([self.compiler, filename+".o"] + compiler_options + [ "-shared", "-o", filename+".so"] + lib_args)
157
+ subprocess.check_call([self.compiler, filename+".o"] + compiler_options + ["-shared", "-o", filename+".so"] + lib_args)
121
158
 
122
159
  self.lib = numpy.ctypeslib.load_library(filename, '.')
123
160
 
@@ -167,8 +204,19 @@ class CFunctions(object):
167
204
  :rtype: float
168
205
  """
169
206
  results = []
170
- for _ in range(self.ITERATIONS):
207
+ for _ in range(self.iterations):
171
208
  value = self.run_kernel(func, c_args, threads, grid)
209
+
210
+ #I would like to replace the following with actually capturing
211
+ #stderr and detecting the error directly in Python, it proved
212
+ #however that capturing stderr for non-Python functions from Python
213
+ #is a rather difficult thing to do
214
+ #
215
+ #The current, less than ideal, scheme uses the convention that a
216
+ #negative time indicates a 'too many resources requested for launch'
217
+ if value < 0.0:
218
+ raise Exception("too many resources requested for launch")
219
+
172
220
  results.append(value)
173
221
  results = sorted(results)
174
222
  return numpy.mean(results[1:-1])
@@ -196,17 +244,10 @@ class CFunctions(object):
196
244
  :returns: A robust average of values returned by the C function.
197
245
  :rtype: float
198
246
  """
199
- time = func(*c_args)
247
+ logging.debug("run_kernel")
248
+ logging.debug("arguments=" + str([str(arg) for arg in c_args]))
200
249
 
201
- #I would like to replace the following with actually capturing
202
- #stderr and detecting the error directly in Python, it proved
203
- #however that capturing stderr for non-Python functions from Python
204
- #is a rather difficult thing to do
205
- #
206
- #The current, less than ideal, scheme uses the convention that a
207
- #negative time indicates a 'too many resources requested for launch'
208
- if time < 0.0:
209
- raise Exception("too many resources requested for launch")
250
+ time = func(*c_args)
210
251
 
211
252
  return time
212
253
 
@@ -240,4 +281,8 @@ class CFunctions(object):
240
281
 
241
282
  def cleanup_lib(self):
242
283
  """ unload the previously loaded shared library """
243
- _ctypes.dlclose(self.lib._handle)
284
+ if not self.using_openmp:
285
+ #this if statement is necessary because shared libraries that use
286
+ #OpenMP will core dump when unloaded, this is a well-known issue with OpenMP
287
+ logging.debug('unloading shared library')
288
+ _ctypes.dlclose(self.lib._handle)