Skip to content

Commit

Permalink
Added benchmark notebook
Browse files Browse the repository at this point in the history
  • Loading branch information
fastlib committed Jan 20, 2023
1 parent 79892e8 commit 29f7024
Show file tree
Hide file tree
Showing 3 changed files with 236 additions and 16 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Features
|**fCWT for real-time Electroencephalography (EEG) analysis** |**fCWT for real-time engine diagnostics** |
|<img src="https://github.com/fastlib/fCWT/blob/main/img/eeg2.png" alt="fcwteeg2" width="400"/>|<img src="https://github.com/fastlib/fCWT/blob/main/img/engine.png" alt="fcwtengine" width="400"/>|

*Based on C++ performance. fCWT is the fastest CWT library in C++ and Matlab. In Python CCWT is faster for shorter signals and fCWT for longer signals. Please see the benchmark section for more details. Raise an issue if you found a new/faster implementation. I will try to add it to benchmark!
*Based on C++ performance. **fCWT is the fastest CWT library in C++, Python and Matlab!** Please see the benchmark section for more details. Raise an issue if you found a new/faster implementation. I will try to add it to benchmark!

Quickstart
============
Expand Down Expand Up @@ -88,16 +88,16 @@ See the Installation section for more details about building fCWT from source fo
Benchmark
========

Columns are formatted as X-Y, where X is signal length in samples and Y the number of frequencies. The benchmark has been performed on a MacBook Pro 2019 having a 2,3 GHz Intel Core i9 4.5 Ghz Boost, 16 GB 2400 MHz DDR4.
Columns are formatted as X-Y, where X is signal length in samples and Y the number of frequencies. The benchmark has been performed on a MacBook Pro 2019 having a 2,3 GHz Intel Core i9 4.5 Ghz Boost, 16 GB 2400 MHz DDR4. See the 'Usage: Benchmark' section for more details about the C++ benchmark. See the [Benchmark Notebook](https://github.com/fastlib/fCWT/blob/main/benchmark.ipynb) for the fCWT Python benchmark.

| Implementation | 10k-300 | 10k-3000 | 100k-300 | 100k-3000 | Speedup factor |
|-----------------------|---------|----------|----------|-----------|----------------|
| fCWT (C++) | 0.005s | 0.04s | 0.03s | 0.32s | - |
| fCWT (Python) | 0.027s | 0.23s | 0.05s | 0.49s | - |
| fCWT (Python) | 0.011s | 0.089s | 0.074s | 0.66s | - |
| fCWT (Matlab) | 0.072s | 0.44s | 0.17s | 1.55s | - |
| | | | | | |
| [CCWT] (Python) | 0.019s | 0.11s | 0.15s | 3.40s | 10.63x |
| [PyWavelets] (Python) | 0.10s | 1.17s | 1.06s | 12.69s | 34.29x |
| [PyWavelets] (Python) | 0.10s | 1.17s | 1.06s | 12.69s | 34.29x |
| Matlab | 0.75s | 0.86s | 1.06s | 13.26s | 35.85x |
| [SsqueezePy] (Python) | 0.04s | 0.43s | 1.16s | 17.76s | 48.00x |
| SciPy (Python) | 0.19s | 1.82s | 2.11s | 18.70s | 50.54x |
Expand Down
220 changes: 220 additions & 0 deletions benchmark.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import fcwt\n",
"import numpy as np\n",
"import timeit"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"fs = 100\n",
"\n",
"n10k = 10000\n",
"n100k = 100000\n",
"\n",
"#Generate signals\n",
"sig_100k = np.sin(2*np.pi*((0.1+(2*np.arange(n100k))/n100k)*(np.arange(n100k)/fs)))\n",
"sig_10k = np.sin(2*np.pi*((0.1+(2*np.arange(n10k))/n10k)*(np.arange(n10k)/fs)))\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"f0 = 1\n",
"f1 = 101\n",
"fn300 = 300\n",
"fn3000 = 3000\n",
"\n",
"#make sure signal is a numpy float array\n",
"sig_100k = np.array(sig_100k, dtype=np.float32)\n",
"sig_10k = np.array(sig_10k, dtype=np.float32)\n",
"\n",
"#initialize Morlet wavelet with wavelet parameter (sigma) 2.0\n",
"morl = fcwt.Morlet(2.0)\n",
"\n",
"#initialize scales\n",
"scales300 = fcwt.Scales(morl, fcwt.FCWT_LINFREQS, fs, f0, f1, fn300)\n",
"scales3000 = fcwt.Scales(morl, fcwt.FCWT_LINFREQS, fs, f0, f1, fn3000)\n",
"\n",
"#initialize fcwt\n",
"nthreads = 8\n",
"use_optimization_plan = True\n",
"use_normalization = False\n",
"fcwt_obj = fcwt.FCWT(morl, nthreads, use_optimization_plan, use_normalization)\n",
"\n",
"#initialize output array\n",
"output_10k_300 = np.zeros((fn300,sig_10k.size), dtype=np.complex64)\n",
"output_100k_300 = np.zeros((fn300,sig_100k.size), dtype=np.complex64)\n",
"output_10k_3000 = np.zeros((fn3000,sig_100k.size), dtype=np.complex64)\n",
"output_100k_3000 = np.zeros((fn3000,sig_100k.size), dtype=np.complex64)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Threads:8\n",
"Calculating optimal scheme for forward FFT with N:2048\n",
"Calculating optimal scheme for backward FFT with N:2048\n",
"Optimization schemes for N: 2048 have been calculated. Next time you use fCWT it will automatically choose the right optimization scheme based on number of threads and signal length.\n",
"Threads:8\n",
"Calculating optimal scheme for forward FFT with N:4096\n",
"Calculating optimal scheme for backward FFT with N:4096\n",
"Optimization schemes for N: 4096 have been calculated. Next time you use fCWT it will automatically choose the right optimization scheme based on number of threads and signal length.\n",
"Threads:8\n",
"Calculating optimal scheme for forward FFT with N:8192\n",
"Calculating optimal scheme for backward FFT with N:8192\n",
"Optimization schemes for N: 8192 have been calculated. Next time you use fCWT it will automatically choose the right optimization scheme based on number of threads and signal length.\n",
"Threads:8\n",
"Calculating optimal scheme for forward FFT with N:16384\n",
"Calculating optimal scheme for backward FFT with N:16384\n",
"Optimization schemes for N: 16384 have been calculated. Next time you use fCWT it will automatically choose the right optimization scheme based on number of threads and signal length.\n",
"Threads:8\n",
"Calculating optimal scheme for forward FFT with N:32768\n",
"Calculating optimal scheme for backward FFT with N:32768\n",
"Optimization schemes for N: 32768 have been calculated. Next time you use fCWT it will automatically choose the right optimization scheme based on number of threads and signal length.\n",
"Threads:8\n",
"Calculating optimal scheme for forward FFT with N:65536\n",
"Calculating optimal scheme for backward FFT with N:65536\n",
"Optimization schemes for N: 65536 have been calculated. Next time you use fCWT it will automatically choose the right optimization scheme based on number of threads and signal length.\n",
"Threads:8\n",
"Calculating optimal scheme for forward FFT with N:131072\n",
"Calculating optimal scheme for backward FFT with N:131072\n",
"Optimization schemes for N: 131072 have been calculated. Next time you use fCWT it will automatically choose the right optimization scheme based on number of threads and signal length.\n"
]
}
],
"source": [
"fcwt_obj.create_FFT_optimization_plan(100000,\"FFTW_MEASURE\")"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"10k-300: 0.011435500299921842 seconds\n"
]
}
],
"source": [
"#10k-300\n",
"a = timeit.timeit('fcwt_obj.cwt(sig_10k, scales300, output_10k_300)', number=10, globals=globals())\n",
"print(\"10k-300: \", a/10, \"seconds\")"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"100k-300: 0.07430814850004026 seconds\n"
]
}
],
"source": [
"#100k-300\n",
"a = timeit.timeit('fcwt_obj.cwt(sig_100k, scales300, output_100k_300)', number=10, globals=globals())\n",
"print(\"100k-300: \", a/10, \"seconds\")"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"10k-3000: 0.08949035639998329 seconds\n"
]
}
],
"source": [
"#10k-3000\n",
"a = timeit.timeit('fcwt_obj.cwt(sig_10k, scales3000, output_10k_3000)', number=10, globals=globals())\n",
"print(\"10k-3000: \", a/10, \"seconds\")"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"100k-3000: 0.6612934732000213 seconds\n"
]
}
],
"source": [
"#100k-3000\n",
"a = timeit.timeit('fcwt_obj.cwt(sig_100k, scales3000, output_100k_3000)', number=10, globals=globals())\n",
"print(\"100k-3000: \", a/10, \"seconds\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.9"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "aee8b7b246df8f9039afb4144a1f6fd8d2ca17a180786b69acc140d282b71a49"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}
24 changes: 12 additions & 12 deletions tutorial.ipynb

Large diffs are not rendered by default.

0 comments on commit 29f7024

Please sign in to comment.