Skip to content
Open
Show file tree
Hide file tree
Changes from 84 commits
Commits
Show all changes
128 commits
Select commit Hold shift + click to select a range
01ba8e8
fixed package name to varname
psyrd1 Nov 18, 2020
8790fb7
removed instruction pylint: disable=C0303,C033
raphdem Nov 18, 2020
a0b4920
fixing default value
raphdem Dec 9, 2020
9a2e439
adding store_value
raphdem Dec 9, 2020
4d99381
Adding data type
sbacchio Dec 9, 2020
1b9d57c
Fixing initialization of Node
sbacchio Dec 9, 2020
7f212e7
Setting values also of variables
sbacchio Dec 9, 2020
912816e
Adding draft of tuner
sbacchio Dec 9, 2020
065321b
added optuna as an optional package
raphdem Dec 17, 2020
100c012
fixed typo
raphdem Dec 17, 2020
5210fc8
a sampler based on the optuna package
raphdem Dec 17, 2020
d683c48
tuner was changed to work with OptunaSampler
raphdem Dec 17, 2020
cbdd411
fixed package name
raphdem Dec 22, 2020
514b2f5
fixed JSON serializable error
raphdem Dec 22, 2020
4bc8238
new pytest file for the Tuner class
raphdem Dec 22, 2020
4a504f0
removing OptunaSampler
raphdem Dec 22, 2020
cbce515
using a list for variables
raphdem Jan 7, 2021
b329937
functions for merging nodes have been added
raphdem Feb 1, 2021
88408d7
changes were made to visualize groups within a graph
raphdem Feb 1, 2021
db50ddd
added documentation
raphdem Feb 1, 2021
c1cf27e
added documentation
raphdem Feb 1, 2021
b3371bf
tests for the optuna class
raphdem Feb 1, 2021
a83aa38
tests for the sampler class
raphdem Feb 1, 2021
1a35102
outline of a new subgraph class that enables the merging of nodes
raphdem Feb 1, 2021
7d75053
formatting changed
raphdem Feb 1, 2021
277e3fe
Removing test/__init__.py
sbacchio Feb 5, 2021
07e5d4a
Few changes
sbacchio Feb 5, 2021
398be09
new tests for merge functions added
raphdem Mar 9, 2021
323acf4
tests commented out after changes in code
raphdem Mar 9, 2021
707ecf1
var_name changed for variables created using alternatives
raphdem Mar 9, 2021
c683d0d
dependencies function was changed
raphdem Mar 9, 2021
ad6c75c
Merge branch 'user/raphdem' of github.com:Lyncs-API/tuneit into user/…
raphdem Mar 9, 2021
859488a
changed visualize function to enable different visualization of nodes…
raphdem Mar 22, 2021
d7c7d9b
1. updated get_attributes function to extract the information used fo…
raphdem Mar 22, 2021
ad50e2b
this file is not needed anymore
raphdem Mar 22, 2021
4f4a6a5
added a copy function for the Tuner class
raphdem Mar 22, 2021
c4d1c11
updated README file with example
raphdem Mar 22, 2021
35a5961
added a boolean precompute attribute to the class Object and now the …
raphdem Mar 22, 2021
86b366c
updated tests to work with the new changes made to the code
raphdem Mar 22, 2021
615f9d8
1. created get_key function and changed other functions (get_node(),_…
raphdem Mar 22, 2021
fcfc272
Adding workflows
sbacchio Mar 25, 2021
466a02b
Removing unwated MPI
sbacchio Mar 25, 2021
454b18b
Updating pylint score (from Github Action)
sbacchio Mar 25, 2021
1bef44d
added tests for the example in README
raphdem Mar 26, 2021
ebbc89a
Merge branch 'user/raphdem' of github.com:Lyncs-API/tuneit into user/…
raphdem Mar 26, 2021
af6c10e
1.added functionality that records the results in a panda dataframe, …
raphdem Apr 2, 2021
1e3be9f
reformatted
raphdem Apr 2, 2021
d20b0ee
added record argument
raphdem Apr 2, 2021
056c203
changed dot_attrs
raphdem Apr 2, 2021
a9a8fa4
changed dot_attrs
raphdem Apr 2, 2021
c266f40
changed crosscheck method to allow a delayed execution
raphdem Apr 2, 2021
b98f396
README: removed example that now exists in docs, conf: added an instr…
raphdem May 11, 2021
a1de802
reformatted
raphdem May 11, 2021
d5c41e3
new documentation pages about installation and some examples along wi…
raphdem May 11, 2021
7d61e47
add_deps now works for all types and a new function get_info was adde…
raphdem May 11, 2021
b0731bb
added an index to each node in the visualization of the graph and the…
raphdem May 11, 2021
6c74fc7
removed function get_attributes and used function get_info from final…
raphdem May 11, 2021
9a8f850
changed the headers of the dataframe
raphdem May 11, 2021
ee5847c
changed data attribute names to contain only one _
raphdem May 13, 2021
3733ecc
updated images to match changes in code
raphdem May 13, 2021
93f8658
updated alternatives to accept a name chosen by the user for the vari…
raphdem May 13, 2021
4203d8c
updated example doc
raphdem May 13, 2021
9918511
deleted files
raphdem May 13, 2021
37521aa
updated example
raphdem May 13, 2021
749b5ba
added pandas to the requirements
raphdem May 13, 2021
77c626c
updated plot
raphdem May 13, 2021
a1e6477
updated tests after get_attributes function was removed from optuna.py
raphdem May 13, 2021
09f0e0b
reformatted
raphdem May 13, 2021
ad3d99a
updated index file
raphdem May 18, 2021
9284700
added option in get_info() for short names
raphdem May 18, 2021
3ae6e6b
added data output node in the visualized graph
raphdem May 18, 2021
7ad7c4d
1. updated datarame headers after get_info() was changed, 2. added *a…
raphdem May 18, 2021
bf3fe80
changed how self.n_trials is assigned
raphdem May 18, 2021
a65f9ac
removed commented code
raphdem May 18, 2021
9c6f60b
reformatted
raphdem May 18, 2021
6955643
pandas are now imported inside record
raphdem May 18, 2021
1722fa8
updated index file
raphdem May 18, 2021
15bf4da
these tests are now only performed if optuna is installed
raphdem May 26, 2021
71efb0c
image used in index file (docs)
raphdem May 26, 2021
9abd1ba
added optuna to extras
raphdem May 26, 2021
a6135c1
changed definition of remove to include *nodes instead of nodes and c…
raphdem May 26, 2021
486c386
removed dependencies function from Object (not used anywhere)
raphdem May 26, 2021
7a151cf
updated index file with code block
raphdem May 26, 2021
25e1ab8
updated image to match code block
raphdem May 26, 2021
14b89a9
alternatives changed to allow the user to pass a name for the functio…
raphdem May 26, 2021
a5d4875
new images for index.rst
raphdem May 26, 2021
e491964
deleted unnecessary file
raphdem May 26, 2021
6e93846
visualize can now be called on a HighLevel object (obj.visualize())
raphdem May 26, 2021
34cd801
the functions benchmark, crosscheck and optimise can now be called on…
raphdem May 26, 2021
5eb61aa
updated index file with additional picture
raphdem May 26, 2021
6ad47a8
fixed alternatives because it was setting the name of the first optio…
raphdem May 26, 2021
48248dc
set HighLevel.optimise equal to optimise
raphdem May 26, 2021
7d11cda
changed how the name in alternatives is set
raphdem May 26, 2021
f48aa1b
updated README file
raphdem Jun 1, 2021
cc8d42b
updated images to match changes in the code
raphdem Jun 1, 2021
efc9d28
updated example.rst file
raphdem Jun 1, 2021
62c30f2
updated image to match changes in example.rst
raphdem Jun 1, 2021
2a72c19
updated picture
raphdem Jun 2, 2021
79ef8a6
removed pictures with wrong extension
raphdem Jun 2, 2021
4cf99fc
images with correct extensions
raphdem Jun 2, 2021
40c6e96
image with correct extension
raphdem Jun 2, 2021
24a7a33
fixed typo
raphdem Jun 2, 2021
696f1bf
updated README file
raphdem Jun 3, 2021
32876e7
fixed image placement
raphdem Jun 3, 2021
38240c5
Updating workflows
sbacchio Jun 3, 2021
85492b1
Updating pylint score (from Github Action)
sbacchio Jun 3, 2021
68debbc
Updating workflow
sbacchio Jun 3, 2021
b11939d
Incrementing version number
sbacchio Jun 3, 2021
5d644e7
Merge branch 'user/raphdem' of github.com:sbacchio/tunable into user/…
sbacchio Jun 3, 2021
d6b305b
Updating workflow
sbacchio Jun 3, 2021
aeacd2b
Updating __init__
sbacchio Jun 3, 2021
2d17504
Updating workflow
sbacchio Jun 3, 2021
dd63ceb
data object values are now passed correctly as kwargs
raphdem Jun 28, 2021
1439039
data object values are now included in sampler_kwargs
raphdem Jun 28, 2021
ee45f03
Merge branch 'user/raphdem' of github.com:Lyncs-API/tuneit into user/…
raphdem Jun 28, 2021
c60ed82
added tests that check if an object is able to be pickled
raphdem Jul 26, 2021
dfad749
changed dict_keys in alternatives to a tuple because they are not pic…
raphdem Jul 26, 2021
5c05746
added __reduce__ methods to classes in order to make them picklable
raphdem Jul 26, 2021
f3afaf5
1. added maximum number of failed trials before error is raise, 2. fi…
raphdem Jul 29, 2021
2f7c361
Updating pylint score (from Github Action)
sbacchio Jul 30, 2021
06f74da
updated setup file with testfixtures
raphdem Jul 30, 2021
e0327ec
Merge branch 'user/raphdem' of github.com:Lyncs-API/tuneit into user/…
raphdem Jul 30, 2021
a4fa61a
Applying black formatting (from Github Action)
sbacchio Jul 30, 2021
7516160
call to optimize updated to match changes about the handling of compu…
raphdem Aug 6, 2021
3ae9344
1. added logging using context managers, 2. added the __reduce__ meth…
raphdem Aug 6, 2021
b737470
formatted
raphdem Aug 6, 2021
990a449
Merge branch 'user/raphdem' of github.com:Lyncs-API/tuneit into user/…
raphdem Aug 6, 2021
d7e216f
Updating pylint score (from Github Action)
sbacchio Aug 6, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions .github/workflows/black_n_pylint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# This workflow runs pylint and updates badge

name: linting

on:
pull_request:
branches:
- "*"

jobs:
black-n-pylint:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
with:
ref: ${{ github.head_ref }}

- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: "3.x"

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install black lyncs_setuptools[pylint]
python setup.py egg_info
sudo pip install `grep -v '^\[' *.egg-info/requires.txt`

- name: Applying black formatting
run: |
black --diff .
black .

- name: Pushing changes if any
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: Applying black formatting (from Github Action)
commit_user_name: sbacchio
commit_user_email: s.bacchio@gmail.com
commit_author: Simone Bacchio <s.bacchio@gmail.com>

- name: Pylint output
run: |
badge=$(lyncs_pylint_badge . | sed "s/\&/\\\&/g")
badge_line=$(awk '/!\[pylint\]/ {print FNR}' README.md)
sed -i "${badge_line}s#.*#${badge}#" README.md

- name: Pushing changes if any
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: Updating pylint score (from Github Action)
commit_user_name: sbacchio
commit_user_email: s.bacchio@gmail.com
commit_author: Simone Bacchio <s.bacchio@gmail.com>

- name: Run lyncs_setuptools
run: |
lyncs_setuptools
43 changes: 43 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# This workflow builds and runs test

name: tests

on:
pull_request:
branches:
- "*"

jobs:
tests:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
py-version:
- 3.6
- 3.7
- 3.8
os:
- ubuntu-latest

steps:
- uses: actions/checkout@v2
with:
ref: ${{ github.head_ref }}

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip

- name: Install via pip
run: |
sudo pip install -e .[all]

- name: Run serial tests
run: |
pytest -v
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[![license](https://img.shields.io/github/license/Lyncs-API/tuneit?logo=github&logoColor=white)](https://github.com/Lyncs-API/tuneit/blob/master/LICENSE)
[![build & test](https://img.shields.io/github/workflow/status/Lyncs-API/tuneit/build%20&%20test?logo=github&logoColor=white)](https://github.com/Lyncs-API/tuneit/actions)
[![codecov](https://img.shields.io/codecov/c/github/Lyncs-API/tuneit?logo=codecov&logoColor=white)](https://codecov.io/gh/Lyncs-API/tuneit)
[![pylint](https://img.shields.io/badge/pylint%20score-8.4%2F10-yellowgreen?logo=python&logoColor=white)](http://pylint.pycqa.org/)
[![pylint](https://img.shields.io/badge/pylint%20score-8.8%2F10-yellowgreen?logo=python&logoColor=white)](http://pylint.pycqa.org/)
[![black](https://img.shields.io/badge/code%20style-black-000000.svg?logo=codefactor&logoColor=white)](https://github.com/ambv/black)

Tuneit is a generic purpose tool for optimizing and crosschecking calculations.
Expand All @@ -19,3 +19,5 @@ The package can be installed via `pip`:
```
pip install [--user] tuneit
```

Comment thread
sbacchio marked this conversation as resolved.

3 changes: 3 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@
# a list of builtin themes.
#
html_theme = "alabaster"
html_sidebars = {
"**": ["globaltoc.html", "relations.html", "sourcelink.html", "searchbox.html"]
}

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
Expand Down
269 changes: 269 additions & 0 deletions docs/example.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,269 @@
Example: A small tuning example using sparse matrices
=====================================================

:code:`tuneit` is imported as shown below along with some other packages that are used in this example:

.. code-block:: python

from tuneit import *
import scipy.sparse as sp
import numpy as np

Firstly, a simple graph is constructed, which computes the multiplication of a sparse matrix with a vector.
The graph contains one variable to be tuned, which represents the different formats that can be used for the sparse matrix.
The following function creates the sparse matrix and by using :code:`alternatives` more options are added for the format that will
be used to express the matrix (available in the :code:`scipy.sparse` package).

.. code-block:: python

@alternatives(
var_name='which_sparse',
coo = lambda matrix: sp.coo_matrix(matrix),
csc = lambda matrix: sp.csc_matrix(matrix),
csr = lambda matrix: sp.csr_matrix(matrix)
)
def bsr(matrix):
return sp.bsr_matrix(matrix)

In this way, we have created a function :code:`bsr` that expresses the given sparse matrix in an appropriate format and a variable
to be tuned. The range of the variable :code:`which_sparse` contains all different options that can be used to express the sparse matrix, which are included in the function above (:code:`coo,csc,csr,bsr`).

The graph takes as input the matrix and the vector to be multiplied. One option is to create a matrix and a vector at random:

.. code-block:: python

mat=scipy.sparse.random(100,100,0.1)
vec=np.random.rand(100)

Or just create two generic data objects, which will take their actual value later on: (this is the option used in this example)

.. code-block:: python

mat=data(info=["shape","dtype"])
vec=data(info=["shape","dtype"])

:code:`data()` creates a generic data object as no specific value is passed in the function. Even though no value is passed, some information
about the new data object can be given using :code:`info`. As shown above, some characteristics about the new objects are given by the
attributes :code:`shape` and :code:`dtype`.

In addition, the :code:`bsr` function constructed previously can now be used. The new :code:`mat` object created after
:code:`bsr` is called on the object :code:`mat` (created above) is a tunable object.

.. code-block:: python

mat=bsr(mat)

The final graph :code:`mul` that expresses the multiplication between the vector :code:`vec` and the sparse matrix :code:`mat` is created
as shown below:

.. code-block:: python

mul=finalize(mat*vec)

..
Do I need more explanations about the finalize function here and why it is needed?
Comment thread
sbacchio marked this conversation as resolved.
Outdated

Furthermore, we define a random sparse matrix and a random vector that will be used later on when actual values are needed to be passed for the :code:`mat,vec` objects created above.

.. code-block:: python

matrix = sp.random(100,100,0.1)
vector = np.random.rand(100)


Visualize
---------

Comment thread
sbacchio marked this conversation as resolved.
The graph can now be visualized using:

.. code-block:: python

visualize(mul)
Comment thread
sbacchio marked this conversation as resolved.
Outdated

The result is shown below:

.. image:: images/visualised_graph1.png

The data objects are shown in rectangles, the functions to be computed are presented in oval shapes, while the variables that have not taken a fixed value yet are shown in red diamonds.

Note: Each node in the graph is represented by its name (such as :code:`bsr`) concatenated with a random sequence of characters, which
is not shown in its visualisation (for instance :code:`bsr-2b53519cefa68a68788760b169fee0b4`).
The small indices included in the nodes of the visualised graph allow the user to distinguish between multiple operations of the same kind
(e.g. multiplications) and to find out the whole unique name of a node in case it is needed in an operation:

For instance the following code should return the whole name of the node that contains the index 2 in the visualization of the graph :code:`mul`:

.. code-block:: python

mul.graph[2]

Comment thread
sbacchio marked this conversation as resolved.

Crosscheck
----------

The function :code:`crosscheck` can be called on the finalised object :code:`mul` as shown below. The function returns a callable sampler
object.

.. code-block:: python

obj = crosscheck(mul)

If it is then called using real values (since the input :code:`mat,vec` of the graph was created using generic data objects) the sampler object
will iterate through all the possible alternative options for the variable of the graph (:code:`which_sparse`) and return :code:`True` only for the ones
that produce the correct result of the graph. The :code:`crosscheck` function is basically a way to check that all alternatives options return
the correct result.

.. code-block:: python

obj(mat=matrix,vec=vector)

The result of the above operation is:

.. table::

============== ========
which_sparse xcheck
============== ========
coo True
csc True
csr True
bsr True
============== ========


Benchmark
---------

The function :code:`benchmark` can be called on the finalised object :code:`mul` as shown below. The function returns a callable sampler
object.

.. code-block:: python

obj = benchmark(mul)

If it is then called using real values (since the input :code:`mat,vec` of the graph was created using generic data objects) the sampler object
will iterate through all the possible alternative options for the variable of the graph (:code:`which_sparse`) and time the execution of graph using each
option. The :code:`benchmark` function is basically a way to compare the execution times of all alternatives options of the variable.

.. code-block:: python

obj(mat=matrix,vec=vector)

The result of the above operation is:

.. table::

============== ============
which_sparse Time
============== ============
coo 448.800 usec
csc 663.900 usec
csr 1.796 msec
bsr 1.551 msec
============== ============

The :code:`bechmark` function has also an argument called :code:`record`, which if it set to :code:`True` allows the execution times of the graph
using alternative options for the variable to be stored in a :code:`panda` dataframe. In addition, now there is the option of also comparing
the execution times that result not only by the various alternatives for the variable, but also different inputs. For example, in the code below
different sizes of inputs are passed in each execution of the sampler. As a result, the returned dataframe :code:`trials` will contain the execution
time of the graph for all combinations of alternative options of the variable and different sizes of inputs.

.. code-block:: python

obj = benchmark(mul, record=True)
for n in for [2**exponent for exponent in range(15)]:
obj(mat=sp.random(n,n,0.1),vec=np.random.rand(n)).run()

The dataframe can be accessed as shown below:

.. code-block:: python

obj.trials

The produced dataframe looks like this:

.. table::


========== ============== ============== ============ ============ ============ ==========
trial_id which_sparse mat_shape mat_dtype vec_shape vec_dtype time
========== ============== ============== ============ ============ ============ ==========
0 coo (1, 1) float64 (1,) float64 0.0004373
1 csc (1, 1) float64 (1,) float64 0.0003272
2 csr (1, 1) float64 (1,) float64 0.0004419
3 bsr (1, 1) float64 (1,) float64 0.0004452
4 coo (2, 2) float64 (2,) float64 0.0002657
... ... ... ... ... ... ...
55 bsr (8192, 8192) float64 (8192,) float64 0.882976
56 coo (16384, 16384) float64 (16384,) float64 0.18082
57 csc (16384, 16384) float64 (16384,) float64 3.64082
58 csr (16384, 16384) float64 (16384,) float64 3.59247
59 bsr (16384, 16384) float64 (16384,) float64 4.25281
========== ============== ============== ============ ============ ============ ==========

The dataframe can be then used to compare different sizes of inputs for the different alternatives for the variable. One way to do this visually
is producing a graph like it is shown below:

.. image:: images/plot.png


Optimize:
---------

For the purposes of this example, we would like to tune the variable :code:`which_sparse` based only on the computation time of the multiplication
(i.e. excluding the time taken by the function :code:`bsr` to construct the matrix). In order to achieve this, a link has to be added
between the multiplication and :code:`which_sparse`, as they are not currently directly connected (:code:`which_sparse` is added as a dependency to the last node
of the graph):

.. code-block:: python

mul.add_deps('which_sparse')

The new link can be observed by running the code:

.. code-block:: python

visualize(mul)

.. image:: images/visualised_graph2.png

In addition, the :code:`bsr` node in the graph needs to be marked as one to be precomputed so that its computation time is not
taken into account when the execution of the graph is timed during the tuning of the variable.
Note: In the following operation we can use the name :code:`bsr` for the node only because it is unique in the graph. If there were
multiple operations of the same kind (e.g. the function :code:`bsr` is used twice in the graph), then the full name of the node would
have to be used.

.. code-block:: python

mul['bsr'].precompute=True

..
should I include a visualisation of the node marked as precomputed?

The only thing left to do is to actually tune the variable by calling the following functions:

.. code-block:: python

obj = optimise(mul,sampler='optuna')

A tuner object has been created by passing the graph to be tuned along with the sampler to be used to the :code:`optimise()` function.
The :code:`optuna` package is one of the options that are offered by :code:`tuneit` to be used as a sampler.

..
maybe include a reference for the optuna package?

Now, the tuner object can simply be called, while also passing actual values for the sparse matrix and the vector. This is necessary, because
during the tuning of the variable the computation of the graph will be carried out for the first time. Each time the tuner object is
called, the tuner executes one more trial and it returns the value that was used for the variable in that trial and the resulting computation
time along with the best trial executed so far.
Note: A trial is a single execution of the objective function (which in this case is the timing of an execution) using a different combination
of values for the variables that are tuned.

For example:

.. code-block:: python

obj(mat=matrix,vec=vector)

..
do I need to include a picture of the result here? (what the tuner returns after it is called a few times)
Binary file added docs/images/computational_graph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/plot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/visualised_graph1.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/visualised_graph2.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading