Skip to content
Snippets Groups Projects
Commit 1ff5c539 authored by Ulrich Kerzel's avatar Ulrich Kerzel
Browse files

CPU profiling

parent 3cea4c5d
No related branches found
No related tags found
No related merge requests found
area.py 0 → 100644
import numpy as np
def area_circle(radius = 2, n_points = 500000):
in_circle = 0
for i in range(0, n_points):
x = np.random.uniform(-radius, radius)
y = np.random.uniform(-radius, radius)
if x**2 + y**2 < radius**2:
in_circle += 1
area = (2*radius)**2 * in_circle/n_points
return area
if __name__ == '__main__':
n_points = 50000
radius = 2
area = area_circle(radius, n_points)
expected_area = np.pi*radius**2
print('The area of the circle is {}, expected result {}, difference: {}'.format(area, expected_area, np.abs(area - expected_area)))
......@@ -80,7 +80,7 @@ python-versions = ">=3.5"
dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy (>=0.900,!=0.940)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "sphinx", "sphinx-notfound-page", "zope.interface"]
docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"]
tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"]
tests_no_zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"]
tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"]
[[package]]
name = "Babel"
......@@ -160,7 +160,15 @@ optional = false
python-versions = ">=3.6.0"
[package.extras]
unicode_backport = ["unicodedata2"]
unicode-backport = ["unicodedata2"]
[[package]]
name = "cloudpickle"
version = "2.2.0"
description = "Extended pickling support for Python objects"
category = "main"
optional = false
python-versions = ">=3.6"
[[package]]
name = "colorama"
......@@ -170,6 +178,17 @@ category = "dev"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
[[package]]
name = "commonmark"
version = "0.9.1"
description = "Python parser for the CommonMark Markdown spec"
category = "main"
optional = false
python-versions = "*"
[package.extras]
test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"]
[[package]]
name = "contourpy"
version = "1.0.6"
......@@ -338,7 +357,7 @@ notebook = ["ipywidgets", "notebook"]
parallel = ["ipyparallel"]
qtconsole = ["qtconsole"]
test = ["pytest (<7.1)", "pytest-asyncio", "testpath"]
test_extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.20)", "pandas", "pytest (<7.1)", "pytest-asyncio", "testpath", "trio"]
test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.20)", "pandas", "pytest (<7.1)", "pytest-asyncio", "testpath", "trio"]
[[package]]
name = "ipython_genutils"
......@@ -367,7 +386,7 @@ testing = ["Django (<3.1)", "colorama", "docopt", "pytest (<7.0.0)"]
name = "Jinja2"
version = "3.1.2"
description = "A very fast and expressive template engine."
category = "dev"
category = "main"
optional = false
python-versions = ">=3.7"
......@@ -539,6 +558,24 @@ category = "main"
optional = false
python-versions = ">=3.7"
[[package]]
name = "line-profiler"
version = "4.0.2"
description = "Line-by-line profiler"
category = "main"
optional = false
python-versions = ">=3.6"
[package.extras]
all = ["Cython", "IPython", "IPython", "cibuildwheel", "cibuildwheel", "cibuildwheel", "cibuildwheel", "cibuildwheel", "cibuildwheel", "cmake", "coverage[toml]", "ninja", "pytest", "pytest-cov", "scikit-build", "ubelt"]
all-strict = ["Cython (==3.0.0a11)", "IPython (==0.13)", "IPython (==0.13)", "cibuildwheel (==2.11.2)", "cibuildwheel (==2.11.2)", "cibuildwheel (==2.11.2)", "cibuildwheel (==2.11.2)", "cibuildwheel (==2.11.2)", "cibuildwheel (==2.8.1)", "cmake (==3.21.2)", "coverage[toml] (==5.3)", "ninja (==1.10.2)", "pytest (==4.6.11)", "pytest-cov (==2.10.1)", "scikit-build (==0.11.1)", "ubelt (==1.0.1)"]
build = ["Cython", "cibuildwheel", "cibuildwheel", "cibuildwheel", "cibuildwheel", "cibuildwheel", "cibuildwheel", "cmake", "ninja", "scikit-build"]
build-strict = ["Cython (==3.0.0a11)", "cibuildwheel (==2.11.2)", "cibuildwheel (==2.11.2)", "cibuildwheel (==2.11.2)", "cibuildwheel (==2.11.2)", "cibuildwheel (==2.11.2)", "cibuildwheel (==2.8.1)", "cmake (==3.21.2)", "ninja (==1.10.2)", "scikit-build (==0.11.1)"]
ipython = ["IPython", "IPython"]
ipython-strict = ["IPython (==0.13)", "IPython (==0.13)"]
tests = ["IPython", "IPython", "coverage[toml]", "pytest", "pytest-cov", "ubelt"]
tests-strict = ["IPython (==0.13)", "IPython (==0.13)", "coverage[toml] (==5.3)", "pytest (==4.6.11)", "pytest-cov (==2.10.1)", "ubelt (==1.0.1)"]
[[package]]
name = "llvmlite"
version = "0.39.1"
......@@ -551,7 +588,7 @@ python-versions = ">=3.7"
name = "MarkupSafe"
version = "2.1.1"
description = "Safely add untrusted strings to HTML/XML markup."
category = "dev"
category = "main"
optional = false
python-versions = ">=3.7"
......@@ -919,13 +956,21 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
name = "Pygments"
version = "2.13.0"
description = "Pygments is a syntax highlighting package written in Python."
category = "dev"
category = "main"
optional = false
python-versions = ">=3.6"
[package.extras]
plugins = ["importlib-metadata"]
[[package]]
name = "pynvml"
version = "11.4.1"
description = "Python Bindings for the NVIDIA Management Library"
category = "main"
optional = false
python-versions = ">=3.6"
[[package]]
name = "pyparsing"
version = "3.0.9"
......@@ -1008,7 +1053,37 @@ urllib3 = ">=1.21.1,<1.27"
[package.extras]
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"]
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
[[package]]
name = "rich"
version = "12.6.0"
description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
category = "main"
optional = false
python-versions = ">=3.6.3,<4.0.0"
[package.dependencies]
commonmark = ">=0.9.0,<0.10.0"
pygments = ">=2.6.0,<3.0.0"
[package.extras]
jupyter = ["ipywidgets (>=7.5.1,<8.0.0)"]
[[package]]
name = "scalene"
version = "1.5.16"
description = "Scalene: A high-resolution, low-overhead CPU, GPU, and memory profiler for Python"
category = "main"
optional = false
python-versions = ">=3.8"
[package.dependencies]
cloudpickle = ">=1.5.0"
Jinja2 = ">=3.0.3"
pynvml = ">=11.0.0"
rich = ">=10.7.0"
wheel = ">=0.36.1"
[[package]]
name = "scikit-learn"
......@@ -1266,10 +1341,21 @@ docs = ["Sphinx (>=3.4)", "sphinx-rtd-theme (>=0.5)"]
optional = ["python-socks", "wsaccel"]
test = ["websockets"]
[[package]]
name = "wheel"
version = "0.38.4"
description = "A built-package format for Python"
category = "main"
optional = false
python-versions = ">=3.7"
[package.extras]
test = ["pytest (>=3.0.0)"]
[metadata]
lock-version = "1.1"
python-versions = "^3.10"
content-hash = "b8c75fa740cec38d32137ea08dcc6352e891b7780ba3bb654e8927f922e4c2be"
content-hash = "f5c90f2e4f83956319a3966021512c363d714b815c784958e1e298f2e680f1f1"
[metadata.files]
anyio = [
......@@ -1405,10 +1491,18 @@ charset-normalizer = [
{file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"},
{file = "charset_normalizer-2.1.1-py3-none-any.whl", hash = "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"},
]
cloudpickle = [
{file = "cloudpickle-2.2.0-py3-none-any.whl", hash = "sha256:7428798d5926d8fcbfd092d18d01a2a03daf8237d8fcdc8095d256b8490796f0"},
{file = "cloudpickle-2.2.0.tar.gz", hash = "sha256:3f4219469c55453cfe4737e564b67c2a149109dabf7f242478948b895f61106f"},
]
colorama = [
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
]
commonmark = [
{file = "commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"},
{file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"},
]
contourpy = [
{file = "contourpy-1.0.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:613c665529899b5d9fade7e5d1760111a0b011231277a0d36c49f0d3d6914bd6"},
{file = "contourpy-1.0.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:78ced51807ccb2f45d4ea73aca339756d75d021069604c2fccd05390dc3c28eb"},
......@@ -1658,6 +1752,51 @@ kiwisolver = [
{file = "kiwisolver-1.4.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:36dafec3d6d6088d34e2de6b85f9d8e2324eb734162fba59d2ba9ed7a2043d5b"},
{file = "kiwisolver-1.4.4.tar.gz", hash = "sha256:d41997519fcba4a1e46eb4a2fe31bc12f0ff957b2b81bac28db24744f333e955"},
]
line-profiler = [
{file = "line_profiler-4.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de5f977c6387e1a9799fdb09e62707e28d9e7be2911ac1fa8132e19dbf2e4ac"},
{file = "line_profiler-4.0.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:967a31032dbc7345b936fc516de59ab92b43913bf9a3a81b4888329f16665222"},
{file = "line_profiler-4.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ba3d088b17a9c902e95c0cb23017f1df1356e33e5b01a4f65c2cba710b78c17"},
{file = "line_profiler-4.0.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5978f48e47328df82d5f3959ba03b1d099c927d4c4bd1ea65bcdd7960af506d6"},
{file = "line_profiler-4.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3ceefb2443504021d3b509a25af2c1232d9866bf0022e97e248fce492e7c2ca7"},
{file = "line_profiler-4.0.2-cp310-cp310-win32.whl", hash = "sha256:38218ffb3a7140843615aa3ba2f90dc0a61d1ebb4b8734ed4e66b9f5386c5811"},
{file = "line_profiler-4.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:1c45d54f8fbeb95016cd83e3e6ee3ae0746b05da612b4d3b2d7600dd3bdf5cee"},
{file = "line_profiler-4.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:76b4778bbafc12ba44846622a083a7a2e2a0214d63bb37478bd42b0a2f226c0c"},
{file = "line_profiler-4.0.2-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b18e84e5d5245337bd157989a1d6d79c08f402caaeb73fe020d927f0cd1cab0"},
{file = "line_profiler-4.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d78ef5527b00c849e4edb42012c4bb036776b46b24ddd64ba4c49f02e79a4fc3"},
{file = "line_profiler-4.0.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:784e1af0901fffcfc5e4172b0eeb4753475d7493aa10898e7742598bd37afa64"},
{file = "line_profiler-4.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:657e5638e2b14140f720a296ae0e5404a3ec3b57f8993de38b8b8d4d364ad232"},
{file = "line_profiler-4.0.2-cp311-cp311-win32.whl", hash = "sha256:1ea823094d3fa4c19bda80f97e23c8968f0de0a26ce0292f940b351886d0006c"},
{file = "line_profiler-4.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:c4be7c7f6995af1b4c98fc7d64910389e139052f04502f75195a8eb783b6c3da"},
{file = "line_profiler-4.0.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6f78d3b7055694e0a375bd2f7ff96c96479beea8ee500e4e4a1e0e8339b46280"},
{file = "line_profiler-4.0.2-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9caea9600d5a6bfd5b3d8833afb3f1866f8a22f0839d1f17c6fcf5e87edea6fa"},
{file = "line_profiler-4.0.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3765aed8434623797b135bdf41239957ca386ffcce4d7f8e5f639757673aa01"},
{file = "line_profiler-4.0.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:803c926aaebc036d6af6f3c428fc5e5eb07d0708a86563b31c5efc170ba55a63"},
{file = "line_profiler-4.0.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:dc25a5483711e9f106cc7820027b0df5adedec4473e492d2d37f95d76aca1b41"},
{file = "line_profiler-4.0.2-cp36-cp36m-win32.whl", hash = "sha256:0cd9e0679e14fa79efcbd23e50027ea7b91dbd73b3f563556be450acedda0dd2"},
{file = "line_profiler-4.0.2-cp36-cp36m-win_amd64.whl", hash = "sha256:3dd66972da651cb48acff95cb5e953c1bbb8d15b84e8d2f03b24c132c2618d1b"},
{file = "line_profiler-4.0.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:518818bea6ff084ffffe1e7f65d345f389259a5d2b12ed4d75b9a62b79ac3268"},
{file = "line_profiler-4.0.2-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6eb20bbc089d166523349af733e8670dde4a94ca4a9eb4a44081f4bc0365552"},
{file = "line_profiler-4.0.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d2dcffabf9794678a709888684541f39b3b6ff2b1fd06365df5a56578f73973"},
{file = "line_profiler-4.0.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f3f8d91b6e8a86790436713a5853aa57718fe378796d452619531cabb54ae8eb"},
{file = "line_profiler-4.0.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:541a5798c1debc6be52090e26096c6a9faf8c9e6608f49d1b7fc6ddba1a16dea"},
{file = "line_profiler-4.0.2-cp37-cp37m-win32.whl", hash = "sha256:4904d263a16e8561ad312b7fa97f19cbf730c4d053c7535b9ea7674a7b2002c9"},
{file = "line_profiler-4.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6970818772e69215734221226a3a94cf1dc5cfc63e700694a42c998b5b2ce22d"},
{file = "line_profiler-4.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7c9585da4003666167373ac219cdaeeaecafa3f8e16ced302e05f3da3956cffc"},
{file = "line_profiler-4.0.2-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:14e9e17e7462325a9f8334815294ac6a319ffa471db0b3c85affd2eeb72f4ab0"},
{file = "line_profiler-4.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37a03c75f478d132555f79216966cea7c5038d3e76311a209cb85d3a2c109c6d"},
{file = "line_profiler-4.0.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:224dff75befa6589673efd11cbb23b5de9086c075eae37aa03d9a426d6b00aac"},
{file = "line_profiler-4.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:930e47bf506cbaeaafd0333289236b0ade553c2bfe11ac09ae276a92813b60a3"},
{file = "line_profiler-4.0.2-cp38-cp38-win32.whl", hash = "sha256:53c4dd01c8f6066db200edb9b99fd6038dcf5582588d0a90c8747713e1cc9cce"},
{file = "line_profiler-4.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:90a957e45bbc15a261d866f5ab46092f61fd7a025701820309ef04f18cdaaf4c"},
{file = "line_profiler-4.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:99e7e78ad515d2f9e70d2536e403c2c26b3990a21ebb070296b22b14e709f1f2"},
{file = "line_profiler-4.0.2-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d715e31962e84100ff3d09caec5a26e940b31675020cee55608be62a236dffc6"},
{file = "line_profiler-4.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac262bd6d87dbdd4959941a699131e4f4daeb03f308eb785775dd61e52a272f1"},
{file = "line_profiler-4.0.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:1a6aa784790a299676409420f1707d6c72456703499503f283fa62106549b928"},
{file = "line_profiler-4.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3b3ffca66ee09fd6c2b1b31336b8510c1142d9f5bd3397fa38ee0648af6272d9"},
{file = "line_profiler-4.0.2-cp39-cp39-win32.whl", hash = "sha256:c3df5fb8a2a2c9b43498f3214cbac871fa7303572c19fe8157f2d95986fc9c4b"},
{file = "line_profiler-4.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:b1f0a6e00d24a1064ee4fbe3ae62406e71b11065aab7aa448c1242035125e74e"},
{file = "line_profiler-4.0.2.tar.gz", hash = "sha256:25e8c9d4248dc48905801851ff8a75b9c74827a0871d118d1104d8e43d7fb0fc"},
]
llvmlite = [
{file = "llvmlite-0.39.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6717c7a6e93c9d2c3d07c07113ec80ae24af45cde536b34363d4bcd9188091d9"},
{file = "llvmlite-0.39.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ddab526c5a2c4ccb8c9ec4821fcea7606933dc53f510e2a6eebb45a418d3488a"},
......@@ -2047,6 +2186,10 @@ Pygments = [
{file = "Pygments-2.13.0-py3-none-any.whl", hash = "sha256:f643f331ab57ba3c9d89212ee4a2dabc6e94f117cf4eefde99a0574720d14c42"},
{file = "Pygments-2.13.0.tar.gz", hash = "sha256:56a8508ae95f98e2b9bdf93a6be5ae3f7d8af858b43e02c5a2ff083726be40c1"},
]
pynvml = [
{file = "pynvml-11.4.1-py3-none-any.whl", hash = "sha256:d27be542cd9d06558de18e2deffc8022ccd7355bc7382255d477038e7e424c6c"},
{file = "pynvml-11.4.1.tar.gz", hash = "sha256:b2e4a33b80569d093b513f5804db0c7f40cfc86f15a013ae7a8e99c5e175d5dd"},
]
pyparsing = [
{file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"},
{file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"},
......@@ -2187,6 +2330,27 @@ requests = [
{file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"},
{file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"},
]
rich = [
{file = "rich-12.6.0-py3-none-any.whl", hash = "sha256:a4eb26484f2c82589bd9a17c73d32a010b1e29d89f1604cd9bf3a2097b81bb5e"},
{file = "rich-12.6.0.tar.gz", hash = "sha256:ba3a3775974105c221d31141f2c116f4fd65c5ceb0698657a11e9f295ec93fd0"},
]
scalene = [
{file = "scalene-1.5.16-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:89df6f28dce1170e6875ebae5424dc928edb281a9d1f080e60ed67932d5fc099"},
{file = "scalene-1.5.16-cp310-cp310-manylinux_2_24_x86_64.whl", hash = "sha256:cf64e179c2d24639f158d89f978d5d7bedc524f423683fd5d915c3b1274b3a74"},
{file = "scalene-1.5.16-cp310-cp310-win_amd64.whl", hash = "sha256:04c89dc567735454cf6d415287c19d9458a0ac7204f8af75670fa8d03a5a61a1"},
{file = "scalene-1.5.16-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f1adb93a00b1ecdef4e1bfcfedf5453b74b5f7ece1637cb6180321e8b4132486"},
{file = "scalene-1.5.16-cp311-cp311-manylinux_2_24_x86_64.whl", hash = "sha256:bab76332f3d2c93336570b40cd6a414ee6bc5027a67ea6e6fea88533d884d377"},
{file = "scalene-1.5.16-cp311-cp311-win_amd64.whl", hash = "sha256:c8d611620278df7b6793f40ee41aadc83e72347ca048e1caed76d3446a1c31ff"},
{file = "scalene-1.5.16-cp37-cp37m-macosx_10_15_universal2.whl", hash = "sha256:9d8ae9ed42af29324b09bcf4769668ec3de1da1a0e07bdd4dbe590f8667bc24a"},
{file = "scalene-1.5.16-cp37-cp37m-manylinux_2_24_x86_64.whl", hash = "sha256:6cd734c96074536e646cc020920dfb5e3075a0b6610f09ab44dd8e381c2176ee"},
{file = "scalene-1.5.16-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:4c6940fc281a479449f126fc0e7003ad1fd903cc5009a93ca69041a0170d397f"},
{file = "scalene-1.5.16-cp38-cp38-manylinux_2_24_x86_64.whl", hash = "sha256:2a5da3756ada283b494a1b66b08297905531e1450f2143cdc58a222a257908d4"},
{file = "scalene-1.5.16-cp38-cp38-win_amd64.whl", hash = "sha256:b6467288c43e65333063bd522c83486a4895869a101a94d0b13a58effa456611"},
{file = "scalene-1.5.16-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:ff7a2e9587ef2d268c81f2684b458a29c1d591f1225c13f7954e0d5d655abfdd"},
{file = "scalene-1.5.16-cp39-cp39-manylinux_2_24_x86_64.whl", hash = "sha256:4b8da9edba2400a6ce1a8daada03fd9f310963a4c04f59d3e7c520e0103a3a9b"},
{file = "scalene-1.5.16-cp39-cp39-win_amd64.whl", hash = "sha256:bc0bd7f9111c8a66f9b83fc362f8e610693181e9de28bdc42efc3a249db588e2"},
{file = "scalene-1.5.16.tar.gz", hash = "sha256:2b09aa9b3c5e59c87a08db38771cb75fc0b4c504e93b4be2203f01177ca054b0"},
]
scikit-learn = [
{file = "scikit-learn-1.1.3.tar.gz", hash = "sha256:bef51978a51ec19977700fe7b86aecea49c825884f3811756b74a3b152bb4e35"},
{file = "scikit_learn-1.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8e9dd76c7274055d1acf4526b8efb16a3531c26dcda714a0c16da99bf9d41900"},
......@@ -2318,3 +2482,7 @@ websocket-client = [
{file = "websocket-client-1.4.1.tar.gz", hash = "sha256:f9611eb65c8241a67fb373bef040b3cf8ad377a9f6546a12b620b6511e8ea9ef"},
{file = "websocket_client-1.4.1-py3-none-any.whl", hash = "sha256:398909eb7e261f44b8f4bd474785b6ec5f5b499d4953342fe9755e01ef624090"},
]
wheel = [
{file = "wheel-0.38.4-py3-none-any.whl", hash = "sha256:b60533f3f5d530e971d6737ca6d58681ee434818fab630c83a734bb10c083ce8"},
{file = "wheel-0.38.4.tar.gz", hash = "sha256:965f5259b566725405b05e7cf774052044b1ed30119b5d586b2703aafe8719ac"},
]
......@@ -11,6 +11,8 @@ numpy = "^1.23.4"
seaborn = "^0.12.1"
scikit-learn = "^1.1.3"
numba = "^0.56.4"
line-profiler = "^4.0.2"
scalene = "^1.5.16"
[tool.poetry.group.dev.dependencies]
......
......@@ -471,7 +471,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.10.6 ('pythonintro-hKmMjISb-py3.10')",
"display_name": "Python 3.10.6 ('pythonintro-NlsZwE_T-py3.10')",
"language": "python",
"name": "python3"
},
......@@ -490,7 +490,7 @@
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "8eb59338b0c14423ef4b72291999b63587c3ee4bd1b8d960807ae48fbf6679f5"
"hash": "e79a103ddccd343bb7d1be701b671c098efc420295b660c764763b93be962cdf"
}
}
},
......
%% Cell type:markdown id: tags:
# Python speed comparison
Inevitably, an argument is made that python is slow.
This is mainly because it is an interpreted languague, unlike compiled languages such as C, C++, Fortran, or others.
While this is true, this is also not the whole picture as we will investigte in this notebook.
Here, we compare three different approaches: a "pure" python implementation, an optimised version, and just-in-time compilation.
As an example, we calculate the area of a circle with given radius using a Monte Carlo integration technique.
We will see that a pure python implementation is indeed rather slow. However, one would not follow such an approach but either use specialised libraries or use a special package called [Numba](https://numba.pydata.org/). The latter is a way to pre-compile parts of the code and then use this during execution. Other approaches such as [Cython](https://cython.org/) exist as well that can also optimise python code.
The advantage of this approach is that we can develop python code as we normally would - and then identify which parts would benefit from further optimisation. \
Compared to other languages, this has the benefit that we can make use of all benefits of python, and in particular, the increase in productivity when developing the code or application, and then optimise specific parts. Experience shows that only few functions would really benefit from such an optimisation, whereas most of the code is more concerned with the application infrastructure, user interaction, etc.
%% Cell type:code id: tags:
``` python
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib as mpl
import seaborn as sns
# "compiled python"
import numba
from numba import jit
# profiler to measure execution speed in more detail
%load_ext line_profiler
```
%% Cell type:markdown id: tags:
## Monte Carlo integration
Before we start with looking at the speed of the various implementations, we first understand how we calculate the area of a circle.
Of course, in this simple setup of a (two-dimensional) circle with radius $r$, we know that the area is given by $A = \pi \cdot r^2$ - however, in more complex scenarios, so such simple formula exists.
One approach is to use random points - this is called a Monte Carlo technique (named after the famous casino in the town with the same name).
Essentially, we "throw" random points on the plane and count how many of them land inside the circle compared to outside. The more points we use, the more accurate the estimate of the area of the circle will be.
In the implementation, we loop over the number of points we want to evaluate, obtain a uniform random number for the point $(x,y)$ and evaluate if the point is inside the circle or outside. The area given by the points inside and outside the circle is an estimate of the area of the circle.
%% Cell type:code id: tags:
``` python
def area_circle(radius = 2, n_points = 500000):
in_circle = 0
x_points = []
y_points = []
x_points_circle = []
y_points_circle = []
for i in range(0, n_points):
x = np.random.uniform(-radius, radius)
y = np.random.uniform(-radius, radius)
if x**2 + y**2 < radius**2:
in_circle += 1
x_points_circle.append(x)
y_points_circle.append(y)
else:
x_points.append(x)
y_points.append(y)
area = (2*radius)**2 * in_circle/n_points
return x_points, y_points, x_points_circle, y_points_circle, area
radius = 2
x_points, y_points, x_points_circle, y_points_circle, area = area_circle(radius, 50000)
expected_area = np.pi*radius**2
print('The area of the circle is {}, expected result {}, difference: {}'.format(area, expected_area, np.abs(area - expected_area)))
sns.scatterplot(x=x_points, y=y_points, label='outside', s=5)
sns.scatterplot(x=x_points_circle, y=y_points_circle, color='red', label='inside', s=5)
plt.show()
```
%% Output
The area of the circle is 12.54272, expected result 12.566370614359172, difference: 0.02365061435917326
%% Cell type:markdown id: tags:
### Native Implementation
Now we use the same code but strip all code that is not related to calculating the area to focus on the speed of the loop.
%% Cell type:code id: tags:
``` python
def area_circle(radius = 2, n_points = 500000):
in_circle = 0
for i in range(0, n_points):
x = np.random.uniform(-radius, radius)
y = np.random.uniform(-radius, radius)
if x**2 + y**2 < radius**2:
in_circle += 1
area = (2*radius)**2 * in_circle/n_points
return area
```
%% Cell type:code id: tags:
``` python
%%time
n_points = 50000
radius = 2
area = area_circle(radius, n_points)
expected_area = np.pi*radius**2
print('The area of the circle is {}, expected result {}, difference: {}'.format(area, expected_area, np.abs(area - expected_area)))
```
%% Output
The area of the circle is 12.53728, expected result 12.566370614359172, difference: 0.029090614359171596
CPU times: user 117 ms, sys: 0 ns, total: 117 ms
Wall time: 117 ms
%% Cell type:markdown id: tags:
We can run the ```line_profiler``` to get a more detailed view where the program spends most of the time.
%% Cell type:code id: tags:
``` python
lprun -f area_circle area_circle()
```
%% Output
Timer unit: 1e-09 s
Total time: 1.4412 s
File: /tmp/ipykernel_974/3957699394.py
Function: area_circle at line 1
Line # Hits Time Per Hit % Time Line Contents
==============================================================
1 def area_circle(radius = 2, n_points = 500000):
2 1 997.0 997.0 0.0 in_circle = 0
3
4 500000 54985724.0 110.0 3.8 for i in range(0, n_points):
5 500000 587101233.0 1174.2 40.7 x = np.random.uniform(-radius, radius)
6 500000 568074290.0 1136.1 39.4 y = np.random.uniform(-radius, radius)
7 392630 171245431.0 436.1 11.9 if x**2 + y**2 < radius**2:
8 392630 59790059.0 152.3 4.1 in_circle += 1
9
10 1 1515.0 1515.0 0.0 area = (2*radius)**2 * in_circle/n_points
11 1 633.0 633.0 0.0 return area
%% Cell type:markdown id: tags:
As expected, most of the execution time is spent in the actual calculations, i.e. the generation of random numberss and the calculation whether or not the newly generated point falls within the circle.
The package "scalene" is a more powerful graphical profiler. We can use it as an example where we place the above code into a separate python program and then execute: ```scalene area.py```. This will then produce a web-page (profile.html by default) that will give us a detailed breakdown of where the program spends most of the time. It's a bit of an overkill for our example here but do try it out...
%% Cell type:markdown id: tags:
### Numpy optimisation
Next, we look at an optimised version using the Python package [NumPy](https://numpy.org/).
In this case, numpy is well suited to our task, in other cases, we would use different optimised packages that are more appropriate for the respective task.
Instead of generating the random numbers one at a time, we let numpy generate arrays - this is much more efficient as the generation can be optimised "behind the scenes" in the numpy package.
Using an efficient filter, we can obtain all points inside the circle in one step, again exploiting the fact that this is highly optimised in the numpy package.
Comparing the run-time of both approaches, we see that the numpy version is faster by a factor of $\approx 50$.
%% Cell type:code id: tags:
``` python
def area_circle_numpy(radius = 2, n_points = 500000):
x_points = np.random.uniform(-radius, radius, size=n_points)
y_points = np.random.uniform(-radius, radius, size=n_points)
radii = x_points*x_points + y_points*y_points
in_circle = radii[radii < radius**2]
area = (2*radius)**2 * len(in_circle)/n_points
return area
```
%% Cell type:code id: tags:
``` python
%%time
area = area_circle_numpy(radius,n_points)
expected_area = np.pi*radius**2
print('The area of the circle is {}, expected result {}, difference: {}'.format(area, expected_area, np.abs(area - expected_area)))
```
%% Output
The area of the circle is 12.59296, expected result 12.566370614359172, difference: 0.026589385640827246
CPU times: user 1.68 ms, sys: 1.22 ms, total: 2.9 ms
Wall time: 3.17 ms
%% Cell type:markdown id: tags:
### Numba
The third approach uses the specialised package [Numba](https://numba.pydata.org/). This works by "passing" our code to a just-in-time compiler (JIT) that then optimises our code. Then, this optimised and compiled code is run instead of the interpreted code from the native python interpreter.
As we can see, this is again significantly faster than even the NumPy version above - although this varies from scenario to scenario.
Depending on how heavily Numba can optmise our code, we can achieve the same or similar performance compared to what we would expect from a C or C++ implementation. As a rule of thumb, numerical calculations can be optimised much better compared to user-interaction, input/output operations, etc.
Note that the only difference here compared to our python native implementation is the addition of the decorator ```@jit(nopython=True)```. This means we can use exactly the same code as before and improve the speed by a factor $\approx 100$ (in this case) by adding this one line. This means that we have all the benefits of writing python code without having to sacrifice performance.
N.B. The first time we execute this, Numba needs to compile the code. Hence, before we evaluate the performance, we need to run the code at least twice to measure the performance without the compilation step.
%% Cell type:code id: tags:
``` python
@jit(nopython=True)
def area_circle_numba(radius = 2, n_points = 500000):
in_circle = 0
for i in range(0, n_points):
x = np.random.uniform(-radius, radius)
y = np.random.uniform(-radius, radius)
if x**2 + y**2 < radius**2:
in_circle += 1
area = (2*radius)**2 * in_circle/n_points
return area
```
%% Cell type:code id: tags:
``` python
%%time
area = area_circle_numba(radius,n_points)
expected_area = np.pi*radius**2
print('The area of the circle is {}, expected result {}, difference: {}'.format(area, expected_area, np.abs(area - expected_area)))
```
%% Output
The area of the circle is 12.57696, expected result 12.566370614359172, difference: 0.010589385640827231
CPU times: user 285 µs, sys: 195 µs, total: 480 µs
Wall time: 487 µs
......
......@@ -156,7 +156,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.10.6 ('pythonintro-hKmMjISb-py3.10')",
"display_name": "Python 3.10.6 64-bit",
"language": "python",
"name": "python3"
},
......@@ -175,7 +175,7 @@
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "8eb59338b0c14423ef4b72291999b63587c3ee4bd1b8d960807ae48fbf6679f5"
"hash": "916dbcbb3f70747c44a77c7bcd40155683ae19c65e1c03b4aa3499c5328201f1"
}
}
},
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment