Skip to content

Commit

Permalink
Merge branch 'ver0.9.0' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
jrenaud90 committed May 23, 2024
2 parents da53ff3 + fad336d commit 02c0c57
Show file tree
Hide file tree
Showing 26 changed files with 624 additions and 707 deletions.
59 changes: 54 additions & 5 deletions .github/workflows/build_wheels_main_pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ jobs:
path: dist/*.tar.gz
name: artifact_sdist

build_macos_wheel:
name: Build MacOS wheel for Python ${{ matrix.python }}
build_macos_latest_wheel:
name: Build MacOS (latest) wheel for Python ${{ matrix.python }}
runs-on: macos-latest
strategy:
# Ensure that a wheel builder finishes even if another fails
Expand Down Expand Up @@ -69,7 +69,56 @@ jobs:
- uses: actions/upload-artifact@v4
with:
path: ./wheelhouse/*.whl
name: artifact_Macos_${{ matrix.python }}_whl
name: artifact_MacosLatest_${{ matrix.python }}_whl

build_macos_13_wheel:
name: Build MacOS-13 (x64-86) wheel for Python ${{ matrix.python }}
runs-on: macos-13
strategy:
# Ensure that a wheel builder finishes even if another fails
fail-fast: false
matrix:
python:
- "3.8"
- "3.9"
- "3.10"
- "3.11"
- "3.12"
steps:
- name: Checkout CyRK
uses: actions/checkout@v4

- name: Install Anaconda
uses: conda-incubator/setup-miniconda@v3
with:
activate-environment: cyrk_test
auto-update-conda: true
python-version: ${{ matrix.python }}
auto-activate-base: false

- name: Conda info
shell: bash -el {0}
run: conda info

- name: install gcc-13 # openMP does not play nice with clang on MacOS; also some versions of macos use older gcc so there is a need to install latest.
shell: bash -el {0}
run: |
brew install gcc@13
- name: Install package
shell: bash -el {0}
run: |
conda install nomkl
conda install pytest matplotlib numba numpy scipy cython
python -m pip install --upgrade build
export CC='gcc-13'
export CPPFLAGS="$CPPFLAGS -Xpreprocessor -fopenmp -lgomp"
python -m build --wheel --outdir ./wheelhouse/
- uses: actions/upload-artifact@v4
with:
path: ./wheelhouse/*.whl
name: artifact_Macos13_${{ matrix.python }}_whl

build_other_wheels:
name: Build ${{ matrix.platform }} wheels
Expand Down Expand Up @@ -97,7 +146,7 @@ jobs:

check_dist:
name: Check sdist
needs: [make_sdist, build_macos_wheel, build_other_wheels]
needs: [make_sdist, build_macos_latest_wheel, build_macos_13_wheel, build_other_wheels]
runs-on: ubuntu-22.04
steps:
- uses: actions/download-artifact@v4
Expand All @@ -109,7 +158,7 @@ jobs:

upload_all:
name: Upload wheels to PyPI
needs: [build_macos_wheel, build_other_wheels, make_sdist, check_dist]
needs: [build_macos_latest_wheel, build_macos_13_wheel, build_other_wheels, make_sdist, check_dist]
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
Expand Down
50 changes: 48 additions & 2 deletions .github/workflows/push_tests_mac.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ on: [push, pull_request, workflow_dispatch]

jobs:

test-macos:
test-macos-latest:
defaults:
run:
shell: bash -el {0}
name: Test CyRK on MacOS
name: Test CyRK on MacOS (latest; arm64)
runs-on: macos-latest
strategy:
fail-fast: false
Expand Down Expand Up @@ -51,3 +51,49 @@ jobs:
- name: Run pytest
shell: bash -el {0}
run: pytest --capture=sys -v Tests/

test-macos-13:
defaults:
run:
shell: bash -el {0}
name: Test CyRK on MacOS (v13; x64-86)
runs-on: macos-13
strategy:
fail-fast: false
matrix:
python-version:
- "3.8"
- "3.9"
- "3.10"
- "3.11"
- "3.12"
steps:
- uses: actions/checkout@v4
- uses: conda-incubator/setup-miniconda@v3
with:
activate-environment: cyrk_test
auto-update-conda: true
python-version: ${{ matrix.python-version }}
auto-activate-base: false

- name: Conda info
shell: bash -el {0}
run: conda info

- name: install gcc-13 # openMP does not play nice with clang on MacOS; also some versions of macos use older gcc so there is a need to install latest.
shell: bash -el {0}
run: |
brew install gcc@13
- name: Install package
shell: bash -el {0}
run: |
conda install nomkl
conda install pytest matplotlib numba numpy scipy cython
export CC="gcc-13"
export CPPFLAGS="$CPPFLAGS -Xpreprocessor -fopenmp -lgomp"
python -m pip install -v .
- name: Run pytest
shell: bash -el {0}
run: pytest --capture=sys -v Tests/
66 changes: 33 additions & 33 deletions Benchmarks/CyRK - SciPy Comparison.ipynb

Large diffs are not rendered by default.

Binary file modified Benchmarks/CyRK_CySolver.pdf
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Benchmarks/CyRK_cyrk_ode.pdf
Binary file not shown.
Binary file modified Benchmarks/CyRK_numba.pdf
Binary file not shown.
Binary file modified Benchmarks/SciPy.pdf
Binary file not shown.
11 changes: 11 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@

## 2024

### v0.9.0 (2024-05-22)

Major Changes:
- Shifted from using the Python-based `PyMem_Alloc`, `PyMem_Free` to c-based `malloc`, `free`.
- CySolver `_solve` method is now gil-free.
- This has led to a 35%--230% speed boost at low values of steps (faster start up).

Other Changes:
- CI will now build x64-86 and arm64 wheels for MacOS (change suggested by @dihm in [#49](https://github.com/jrenaud90/CyRK/issues/49)).
- Did have to use this `nomkl` [workaround](https://stackoverflow.com/questions/53014306/error-15-initializing-libiomp5-dylib-but-found-libiomp5-dylib-already-initial) which may cause problems. TBD.

#### v0.8.8 (2024-04-30)

New Features:
Expand Down
2 changes: 1 addition & 1 deletion CyRK/cy/common.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ cdef void interpolate(
size_t t_len_reduced,
size_t target_len,
bint is_complex
) noexcept
) noexcept nogil

cdef size_t find_expected_size(
size_t y_size,
Expand Down
7 changes: 4 additions & 3 deletions CyRK/cy/common.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ from libc.math cimport fmax, fmin, floor
from libc.math cimport INFINITY as INF
from libc.float cimport DBL_EPSILON as EPS
from libc.stdint cimport SIZE_MAX, INT32_MAX
from libc.stdlib cimport free

from CyRK.utils.utils cimport allocate_mem, reallocate_mem, free_mem
from CyRK.array.interp cimport interp_array_ptr, interp_complex_array_ptr
Expand Down Expand Up @@ -46,7 +47,7 @@ cdef void interpolate(
size_t t_len_reduced,
size_t target_len,
bint is_complex
) noexcept:
) noexcept nogil:
""" Interpolate the results of a successful integration over the user provided time domain, `time_domain_full`. """

# Setup loop variables
Expand Down Expand Up @@ -95,10 +96,10 @@ cdef void interpolate(
finally:
# Release memory of any temporary variables
if not (array_slice_ptr is NULL):
free_mem(array_slice_ptr)
free(array_slice_ptr)
array_slice_ptr = NULL
if not (interpolated_array_slice_ptr is NULL):
free_mem(interpolated_array_slice_ptr)
free(interpolated_array_slice_ptr)
interpolated_array_slice_ptr = NULL

cdef size_t find_expected_size(
Expand Down
50 changes: 26 additions & 24 deletions CyRK/cy/cyrk.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

import cython

from libc.stdlib cimport free

import numpy as np
cimport numpy as np

Expand Down Expand Up @@ -867,14 +869,14 @@ def cyrk_ode(
else:
# Clear the storage arrays used during the step loop
if not (time_domain_array_ptr is NULL):
free_mem(time_domain_array_ptr)
free(time_domain_array_ptr)
time_domain_array_ptr = NULL
if not (y_results_array_ptr is NULL):
free_mem(y_results_array_ptr)
free(y_results_array_ptr)
y_results_array_ptr = NULL
if capture_extra:
if not (extra_array_ptr is NULL):
free_mem(extra_array_ptr)
free(extra_array_ptr)
extra_array_ptr = NULL

# Integration was not successful. Leave the solution pointers as length 1 nan arrays.
Expand Down Expand Up @@ -965,17 +967,17 @@ def cyrk_ode(

# Replace old pointers with new interpolated pointers and release the memory for the old stuff
if not (solution_extra_ptr is NULL):
free_mem(solution_extra_ptr)
free(solution_extra_ptr)
solution_extra_ptr = interpolated_solution_extra_ptr
interpolated_solution_extra_ptr = NULL

# Replace old pointers with new interpolated pointers and release the memory for the old stuff
if not (solution_t_ptr is NULL):
free_mem(solution_t_ptr)
free(solution_t_ptr)
solution_t_ptr = interpolated_solution_t_ptr
interpolated_solution_t_ptr = NULL
if not (solution_y_ptr is NULL):
free_mem(solution_y_ptr)
free(solution_y_ptr)
solution_y_ptr = interpolated_solution_y_ptr
interpolated_solution_y_ptr = NULL

Expand All @@ -998,14 +1000,14 @@ def cyrk_ode(
solution_y_view[extra_start + j, i] = solution_extra_ptr[i * num_extra + j]
# Free solution arrays
if not (solution_t_ptr is NULL):
free_mem(solution_t_ptr)
free(solution_t_ptr)
solution_t_ptr = NULL
if not (solution_y_ptr is NULL):
free_mem(solution_y_ptr)
free(solution_y_ptr)
solution_y_ptr = NULL
if capture_extra:
if not (solution_extra_ptr is NULL):
free_mem(solution_extra_ptr)
free(solution_extra_ptr)
solution_extra_ptr = NULL

# Update integration message
Expand All @@ -1027,55 +1029,55 @@ def cyrk_ode(
finally:
# Free pointers made from user inputs
if not (tol_ptrs is NULL):
free_mem(tol_ptrs)
free(tol_ptrs)
tol_ptrs = NULL
if not (t_eval_ptr is NULL):
free_mem(t_eval_ptr)
free(t_eval_ptr)
t_eval_ptr = NULL

# Free pointers used to track y, dydt, and any extra outputs
if not (y_storage_ptrs is NULL):
free_mem(y_storage_ptrs)
free(y_storage_ptrs)
y_storage_ptrs = NULL
if not (extra_output_init_ptr is NULL):
free_mem(extra_output_init_ptr)
free(extra_output_init_ptr)
extra_output_init_ptr = NULL
if not (extra_output_ptr is NULL):
free_mem(extra_output_ptr)
free(extra_output_ptr)
extra_output_ptr = NULL

# Free RK Temp Storage Array
if not (K_ptr is NULL):
free_mem(K_ptr)
free(K_ptr)
K_ptr = NULL

# Free other pointers that should have been freed in main loop, but in case of an exception they were missed.
if not (solution_t_ptr is NULL):
free_mem(solution_t_ptr)
free(solution_t_ptr)
solution_t_ptr = NULL
if not (solution_y_ptr is NULL):
free_mem(solution_y_ptr)
free(solution_y_ptr)
solution_y_ptr = NULL
if not (solution_extra_ptr is NULL):
free_mem(solution_extra_ptr)
free(solution_extra_ptr)
solution_extra_ptr = NULL
if not (interpolated_solution_t_ptr is NULL):
free_mem(interpolated_solution_t_ptr)
free(interpolated_solution_t_ptr)
interpolated_solution_t_ptr= NULL
if not (interpolated_solution_y_ptr is NULL):
free_mem(interpolated_solution_y_ptr)
free(interpolated_solution_y_ptr)
interpolated_solution_y_ptr = NULL
if not (interpolated_solution_extra_ptr is NULL):
free_mem(interpolated_solution_extra_ptr)
free(interpolated_solution_extra_ptr)
interpolated_solution_extra_ptr = NULL
if not (time_domain_array_ptr is NULL):
free_mem(time_domain_array_ptr)
free(time_domain_array_ptr)
time_domain_array_ptr = NULL
if not (y_results_array_ptr is NULL):
free_mem(y_results_array_ptr)
free(y_results_array_ptr)
y_results_array_ptr = NULL
if not (extra_array_ptr is NULL):
free_mem(extra_array_ptr)
free(extra_array_ptr)
extra_array_ptr = NULL

return solution_t, solution_y, success, message
Loading

0 comments on commit 02c0c57

Please sign in to comment.