Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GSoC 2024] Binding PyElastica with Elastica++ #391

Merged
merged 65 commits into from
Sep 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
7a1fe25
Switch to scikit_build_core, remove setup.py
ankith26 May 30, 2024
060f94f
Add basic pybind11 example with meson buildsystem
ankith26 May 30, 2024
a587b65
Start integrating dependencies
ankith26 Jun 9, 2024
8c36584
elasticapp _batch_matmul ports with benchmarking
ankith26 Jun 13, 2024
3e05a9e
add math utility libraries
skim0119 Jun 14, 2024
b3221cd
add blaze traits
skim0119 Jun 14, 2024
ecedea5
Wrap and test everything in BlazeLinearAlgebra.hpp
ankith26 Jun 23, 2024
d612817
python-binding template for vector/matrix/tensor
skim0119 Jun 24, 2024
fb7f32d
include SO3 backend implementation
skim0119 Jun 26, 2024
f66d050
Fix Utilities/Math/Python issues and make it build
ankith26 Jul 5, 2024
3737d5c
Add elasticapp documentation
ankith26 Jul 7, 2024
4e7a04b
port linalg to use Utils/Math/Python objects
ankith26 Jul 7, 2024
f9d4d00
Update README.md
skim0119 Jul 10, 2024
7d45e74
Add batchcross benchmarking
ankith26 Jul 10, 2024
f1eaef8
Setup optimization blaze defines globally
ankith26 Jul 10, 2024
a61a445
revert: __str__ for blaze objects. Other print-related methods are ad…
skim0119 Jul 11, 2024
2e34cdd
feat: Add bound check during blaze setter
skim0119 Jul 11, 2024
99ff10f
Add default simulator frames definition
skim0119 Jul 11, 2024
d03eb97
binding: elastica tags
skim0119 Jul 11, 2024
23cf020
add elastica::tags and system-type structure
skim0119 Jul 11, 2024
9802213
files: CosseratRod system
skim0119 Jul 11, 2024
4bd8a3a
Add backend CI
ankith26 Jul 11, 2024
47952a7
file: Add MakeString
skim0119 Jul 12, 2024
bcb7ad8
Merge branch 'ankith26-gsoc' of https://github.com/ankith26/PyElastic…
skim0119 Jul 12, 2024
d005f62
remove pretty print for now
skim0119 Jul 12, 2024
5b28ec7
files: add Rod-related traits and include trees
skim0119 Jul 12, 2024
b42fab3
files: add system states
skim0119 Jul 12, 2024
ee2fa43
files: common features for system
skim0119 Jul 12, 2024
b393ab0
Update elasticapp.yml
skim0119 Jul 12, 2024
946459a
files: add Materials
skim0119 Jul 12, 2024
1252253
Update elasticapp.yml
skim0119 Jul 12, 2024
54a2afa
files: block concepts
skim0119 Jul 12, 2024
ed8124e
files: add system configuration
skim0119 Jul 12, 2024
7c43877
pybind: add PyTags
skim0119 Jul 12, 2024
ca9025f
remove ::elastica::Time temporarily to detach from Time madules
skim0119 Jul 12, 2024
575997c
files: add error handling
skim0119 Jul 12, 2024
e182636
files: module settings
skim0119 Jul 13, 2024
1bfb5d4
files: block headers
skim0119 Jul 13, 2024
63b1c27
Handle brigand in buildscript instead of wrap
ankith26 Jul 13, 2024
d92a09c
files: necessary utils
skim0119 Jul 13, 2024
96f67a3
Merge branch 'ankith26-gsoc' of https://github.com/ankith26/PyElastic…
skim0119 Jul 13, 2024
acf83d4
files: component helpers and names
skim0119 Jul 13, 2024
cf55e22
files: add missing math utility files
skim0119 Jul 13, 2024
818de4d
files: add missing utils
skim0119 Jul 13, 2024
8609208
Update BindCosseratRod.cpp
skim0119 Jul 13, 2024
8da7f85
add rod construction script
skim0119 Jul 13, 2024
5da6a9e
Implement inv_rotate in elasticapp._rotations
ankith26 Jul 14, 2024
25c6237
Port more inv_rotate tests
ankith26 Jul 14, 2024
37e5860
Implement rotate in elasticapp._rotations
ankith26 Jul 15, 2024
a984130
fix: remove pretty type
skim0119 Jul 20, 2024
177ac70
Merge branch 'ankith26-gsoc' of https://github.com/ankith26/PyElastic…
skim0119 Jul 20, 2024
17ac94e
Start work the CosseratRod bindings
ankith26 Jul 21, 2024
6c47988
Fix_PyCosseratRods module compilation
ankith26 Aug 4, 2024
579c700
Add a basic test for CosseratRod attributes
ankith26 Aug 4, 2024
151a260
add auto-import logic to elasticapp
ankith26 Aug 4, 2024
23ef432
remove twisted rod and old-damping model
skim0119 Aug 8, 2024
187c20e
add pretty type for pybind
skim0119 Aug 8, 2024
ee41753
add clang-format
skim0119 Aug 8, 2024
b3cc4f8
pretty type pybind getters and variable names
skim0119 Aug 8, 2024
a674997
fix formatting
skim0119 Aug 8, 2024
6a8f2a1
Fix _PyTags link issues
ankith26 Aug 10, 2024
70a073b
Remove failing test, that isn't neeeded anymore
ankith26 Aug 10, 2024
1409988
Add _CosseratRodBlock attributes testing
ankith26 Aug 11, 2024
dd2bac1
Remove all unneeded cmake code
ankith26 Aug 21, 2024
2dfc94e
Added some more doc comments
ankith26 Aug 25, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
37 changes: 37 additions & 0 deletions .github/workflows/elasticapp.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: elasticapp (Elastica++ based backend) tests

# trigger run only on changes to the backend folder.
on:
push:
paths:
- backend/**
pull_request:
paths:
- backend/**

jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
python-version: ["3.10", "3.11"] #, "3.12"]
os: [ubuntu-latest] # , macos-latest]

steps:
- uses: actions/checkout@v2

- name: Set up Python ${{ matrix.python-version }}
uses: actions/[email protected]
with:
python-version: ${{ matrix.python-version }}

- name: Install PyElastica
run: pip install . -v

- name: Install elasticapp backend
run: pip install ./backend -v

- name: Run elasticapp tests
run: |
python -m pip install pytest
pytest backend/tests
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,6 @@ outcmaes/*

# csv files
*.csv

# ./backend dependencies
deps
17 changes: 17 additions & 0 deletions backend/.clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
# We'll use defaults from the Google style.
# See http://clang.llvm.org/docs/ClangFormat.html for help.
Language: Cpp
BasedOnStyle: Google
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
PointerAlignment: Left
DerivePointerAlignment: false
FixNamespaceComments: true
IncludeCategories:
- Regex: "^<.*"
Priority: 1
- Regex: ".*"
Priority: 2
NamespaceIndentation: All
SortIncludes: false
10 changes: 10 additions & 0 deletions backend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,13 @@ install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps

subprojects/packagecache

subprojects/blaze
subprojects/blaze_tensor
subprojects/brigand
subprojects/cxxopts-3.1.1
subprojects/sleef
subprojects/tbb
subprojects/yaml-cpp
113 changes: 0 additions & 113 deletions backend/CMakeLists.txt

This file was deleted.

44 changes: 44 additions & 0 deletions backend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Elasticapp backend for PyElastica

This file serves as the documentation for the `elasticapp` backend.

## Installation

In the root of the PyElastica source tree, run the following command

```
pip install ./backend
```

> Make sure you install the package from _PyElastica source tree_.

This command will take care of installation of all build-time dependencies, compilation of C++ source files and install the a python package called `elasticapp`.

## Testing

Make sure you have `pytest` installed. In the root of the PyElastica source tree, run the following command

```
pytest backend/tests
```

## Benchmarking

Standalone scripts for benchmarking purposes are available in `backend/benchmarking` folder.

### Benchmarking `matmul`

For benchmarking various `matmul` implementations, run

```
python3 backend/benchmarking/matmul.py
```

## Contributed By

- Tejaswin Parthasarathy (Teja)
- [Seung Hyun Kim](https://github.com/skim0119)
- Ankith Pai
- [Yashraj Bhosale](https://github.com/bhosale2)
- Arman Tekinalp
- Songyuan Cui
50 changes: 50 additions & 0 deletions backend/benchmarking/batchcross.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from elasticapp._linalg_numpy import batch_cross
from elasticapp._linalg import batch_cross as batch_cross_final
from elasticapp._PyArrays import Matrix
from elastica._linalg import _batch_cross
import numpy
import time

# warm up jit for fair comparison
random_1 = numpy.random.random((3, 1))
random_2 = numpy.random.random((3, 1))
out1 = _batch_cross(random_1, random_2)


def benchmark_batchsize(funcs: list, batches: list[int], num_iterations: int = 1000):
ret: dict = {}
for batch_size in batches:
random_a = numpy.random.random((3, batch_size))
random_b = numpy.random.random((3, batch_size))

ret[batch_size] = {}
for func_name, func, func_wrap in funcs:
random_a_w = func_wrap(random_a) if func_wrap else random_a
random_b_w = func_wrap(random_b) if func_wrap else random_b

start = time.perf_counter()
for _ in range(num_iterations):
func(random_a_w, random_b_w)

ret[batch_size][func_name] = (time.perf_counter() - start) / num_iterations

return ret


results = benchmark_batchsize(
[
("pyelastica", _batch_cross, None),
("elasticapp_blaze_copy", batch_cross, None),
("elasticapp_blaze_final", batch_cross_final, Matrix),
],
[2**i for i in range(14)],
)
for size, data in results.items():
pyelastica = data["pyelastica"]
elasticapp_blaze_copy = data["elasticapp_blaze_copy"]
elasticapp_blaze_final = data["elasticapp_blaze_final"]
print(f"{size = }")
print(f"{pyelastica = }")
print(f"{elasticapp_blaze_copy = }, ratio: {elasticapp_blaze_copy / pyelastica}")
print(f"{elasticapp_blaze_final = }, ratio: {elasticapp_blaze_final / pyelastica}")
print()
46 changes: 46 additions & 0 deletions backend/benchmarking/inv_rotate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from elasticapp._rotations import inv_rotate, inv_rotate_scalar
from elasticapp._PyArrays import Tensor
from elastica._rotations import _inv_rotate
import numpy
import time

# warm up jit for fair comparison
random_1 = numpy.random.random((3, 3, 1))
out1 = _inv_rotate(random_1)


def benchmark_batchsize(funcs: list, batches: list[int], num_iterations: int = 1000):
ret: dict = {}
for batch_size in batches:
random_a = numpy.random.random((3, 3, batch_size))

ret[batch_size] = {}
for func_name, func, func_wrap in funcs:
random_a_w = func_wrap(random_a) if func_wrap else random_a

start = time.perf_counter()
for _ in range(num_iterations):
func(random_a_w)

ret[batch_size][func_name] = (time.perf_counter() - start) / num_iterations

return ret


results = benchmark_batchsize(
[
("pyelastica", _inv_rotate, None),
("elasticapp_simd", inv_rotate, Tensor),
("elasticapp_scalar", inv_rotate_scalar, Tensor),
],
[2**i for i in range(14)],
)
for size, data in results.items():
pyelastica = data["pyelastica"]
elasticapp_simd = data["elasticapp_simd"]
elasticapp_scalar = data["elasticapp_scalar"]
print(f"{size = }")
print(f"{pyelastica = }")
print(f"{elasticapp_simd = }, ratio: {elasticapp_simd / pyelastica}")
print(f"{elasticapp_scalar = }, ratio: {elasticapp_scalar / pyelastica}")
print()
62 changes: 62 additions & 0 deletions backend/benchmarking/matmul.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
from elasticapp._linalg_numpy import (
batch_matmul_naive,
batch_matmul_blaze,
batch_matmul,
)
from elasticapp._linalg import batch_matmul as batch_matmul_final
from elasticapp._PyArrays import Tensor
from elastica._linalg import _batch_matmul
import numpy
import time

# warm up jit for fair comparison
random_1 = numpy.random.random((3, 3, 1))
random_2 = numpy.random.random((3, 3, 1))
out1 = _batch_matmul(random_1, random_2)


def benchmark_batchsize(funcs: list, batches: list[int], num_iterations: int = 1000):
ret: dict = {}
for batch_size in batches:
random_a = numpy.random.random((3, 3, batch_size))
random_b = numpy.random.random((3, 3, batch_size))

ret[batch_size] = {}
for func_name, func, func_wrap in funcs:
random_a_w = func_wrap(random_a) if func_wrap else random_a
random_b_w = func_wrap(random_b) if func_wrap else random_b

start = time.perf_counter()
for _ in range(num_iterations):
func(random_a_w, random_b_w)

ret[batch_size][func_name] = (
time.perf_counter() - start
) / num_iterations

return ret


results = benchmark_batchsize(
[
("pyelastica", _batch_matmul, None),
("elasticapp_naive", batch_matmul_naive, None),
("elasticapp_blaze", batch_matmul_blaze, None),
("elasticapp_blaze_copy", batch_matmul, None),
("elasticapp_blaze_final", batch_matmul_final, Tensor),
],
[2**i for i in range(14)],
)
for size, data in results.items():
pyelastica = data["pyelastica"]
elasticapp_naive = data["elasticapp_naive"]
elasticapp_blaze = data["elasticapp_blaze"]
elasticapp_blaze_copy = data["elasticapp_blaze_copy"]
elasticapp_blaze_final = data["elasticapp_blaze_final"]
print(f"{size = }")
print(f"{pyelastica = }")
print(f"{elasticapp_naive = }, ratio: {elasticapp_naive / pyelastica}")
print(f"{elasticapp_blaze = }, ratio: {elasticapp_blaze / pyelastica}")
print(f"{elasticapp_blaze_copy = }, ratio: {elasticapp_blaze_copy / pyelastica}")
print(f"{elasticapp_blaze_final = }, ratio: {elasticapp_blaze_final / pyelastica}")
print()
Loading
Loading