<commit_before>

Tuning Host Code
================

With the kernel tuner it is also possible to tune the host code of your GPU programs, or even just any C function for that matter.
Tuning the host code can be useful when it contains parameters that have impact on the performance of kernel on the GPU, such as the number of
streams you use to execute a kernel across multiple streams. Another example is when you want to include the data transfers between
host and device into your tuning setup, or tune for different methods of moving data between host and device.

There are few differences with tuning just a single CUDA or OpenCL kernel, to list them:
* You have to specify the lang="C" option.
* The C function should return a ``float``
* You have to do your own timing in C

You have to specify the language as "C" because the kernel tuner will be calling a host function, this means that the kernel
tuner will have to interface with C and in fact uses a different backend. This also means you can use this way of tuning
without having PyCuda installed, because the C functions interface calls the CUDA compiler directly.

The C function should return a float, this is the convention used by the kernel tuner. The returned float is also the number
that you are tuning for. Meaning that this does not necessarily needs to be time, you could also optimize a program for
a different quality, as long as you can express that quality in a single floating-point value. When benchmarking an instance
of the parameter space the returned floats will be averaged for the multiple runs in the same way as with direct CUDA or OpenCL kernel tuning.

By itself the C language does not provide any very precise timing functions. If you are tuning the host code of a CUDA program you can use
CUDA Events to do the timing for you. However, if you are using plain C then you have to supply your own timing function. In the ``examples/c``
directory we have included a file ``timer.h`` that contains a very simple, but accurate timing function for Intel processors. To see how
to use that you can look at the minimal C example in ``examples/c/vector_add.py``. 
<commit_msg>fixing doc<commit_after>

Tuning Host Code
----------------

With the kernel tuner it is also possible to tune the host code of your GPU programs, or even just any C function for that matter.
Tuning the host code can be useful when it contains parameters that have impact on the performance of kernel on the GPU, such as the number of
streams you use to execute a kernel across multiple streams. Another example is when you want to include the data transfers between
host and device into your tuning setup, or tune for different methods of moving data between host and device.

There are few differences with tuning just a single CUDA or OpenCL kernel, to list them:
* You have to specify the lang="C" option.
* The C function should return a ``float``
* You have to do your own timing in C

You have to specify the language as "C" because the kernel tuner will be calling a host function, this means that the kernel
tuner will have to interface with C and in fact uses a different backend. This also means you can use this way of tuning
without having PyCuda installed, because the C functions interface calls the CUDA compiler directly.

The C function should return a float, this is the convention used by the kernel tuner. The returned float is also the number
that you are tuning for. Meaning that this does not necessarily needs to be time, you could also optimize a program for
a different quality, as long as you can express that quality in a single floating-point value. When benchmarking an instance
of the parameter space the returned floats will be averaged for the multiple runs in the same way as with direct CUDA or OpenCL kernel tuning.

By itself the C language does not provide any very precise timing functions. If you are tuning the host code of a CUDA program you can use
CUDA Events to do the timing for you. However, if you are using plain C then you have to supply your own timing function. In the ``examples/c``
directory we have included a file ``timer.h`` that contains a very simple, but accurate timing function for Intel processors. To see how
to use that you can look at the minimal C example in ``examples/c/vector_add.py``. 

{'fraction_non_alphanumeric': 0.03519333178976615, 'fraction_numerical': 0.0, 'mean_word_length': 4.155131264916467, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1168868', 'n_tokens_mistral': 1021, 'n_tokens_neox': 981, 'n_words': 757}