SIMD-accelerated library for list computations
Project description
Simdlib - SIMD-accelerated list operations in python
A case study into how NEON SIMD instrinsics on macos can accelerate list operations
Why do we care?
Operations on lists of data can be found applicable in many computing applications, from finance to LLMs to databases.
Moreover, Python is notorious for being slow due to many factors (interpreter, gc, abstraction layers, etc) and being able to speed up python applications with minimal source changes is a huge win.
Why SIMD Intrinsics?
This library is for use by ARM architectures. Specifically, it utilizes the NEON SIMD extension to provide it's capabilities. We choose to focus on SIMD intrinsics because:
-
Reduces reliance on the compiler to produce performant code. Even compiler hints aren't guaranteed to produce the assembly we want
-
Python C extension allows us to make lower-level optimizations to how our library works
Disadvantages of this approach include:
-
Stuck to making platform-specific changes
-
Error-prone / messier code
How it works
Simdlib is written using the Python C Extension library. This allows us to cast python list objects into their C counterparts. Each operation essentially follows the same process. We load in an empty vector into a vector register. We then load 4 elements at a time into the vector register, then use an explicit instruction to accumulate those values into a variable. Not every list is going to have len(list) % 4 == 0, so with the remaining elements we accumulate them serially.
Examples
Simdlib comes equipped with common accumulate operations:
>>> import simdlib
>>> simdlib.sum_list([1, 2, 3])
6
>>> simdlib.multiply_list([1, 2, 3])
6
>>> simdlib.min_list([1, 2, 3])
1
>>> simdlib.max_list([1, 2, 3])
3
It also comes with mapping operations:
>>> simdlib.add_each_list([1, 2, 3], 1)
[2, 3, 4]
Benchmark Results
Included in the the tests folder is benchmarking code. Running on a M3 Pro with Sequoia 15.5. Three different methods were tested. We have the naive implementation, which is a serial for loop over elements. We have our SIMD-accelerated implementation, which replaces the for loop with a library call. Then, we also include a numpy example to show that in certain circumstances it can beat it as well. We test out various accumulation operations on a nested list object.
I was able to get the following results (in secs) running 100 iterations each time:
sum op:
naive 0.6113339829444885
optimized 0.5228000903129577
numpy_func 0.8831670045852661
multiply op:
naive 0.6138886904716492
optimized 0.5130776786804199
numpy_func 0.8746641612052918
min op:
naive 0.6658641147613525
optimized 0.5254337954521179
numpy_func 0.894232234954834
209.55441308021545
max op:
naive 0.7053544044494628
optimized 0.5487733411788941
numpy_func 0.9244655680656433
any op:
naive 0.5905903220176697
optimized 0.5639568519592285
numpy_func 0.9229762864112854
all op:
naive 0.5866790390014649
optimized 0.5561843490600586
numpy_func 0.9211705374717712
In this specific case, we see that our optimized functions perform best. This is likely due to the fact that versus the naive version, we utilize SIMD operations vs. performing each accumulate step individually, and vs. our numpy implementation we can operate on native python lists vs converting to np.arrays.
A "real-life" example is also available in tests/stock_example.py which demonstrates using simdlib to calculate the sharpe ratio from a generated list of stock prices. The results are as follows:
naive 0.1298867130279541
optimized 0.10430599689483643
numpy 0.11439987182617188
Setup
Create venv and setup dependencies:
pip install requirements.txt
Install the source distribution locally:
pip install -e .
To install from PyPi:
pip install simdlib
PyPi distribution page: https://pypi.org/project/simdlib/
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file simdlib-0.1.1.tar.gz.
File metadata
- Download URL: simdlib-0.1.1.tar.gz
- Upload date:
- Size: 10.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3145266ae11c4d1e34a831461ce81a7b6d6881af41a42eac84f4236d73f13b56
|
|
| MD5 |
28c84348f05607991f67ac7e175d0e98
|
|
| BLAKE2b-256 |
0b39f728a20f9c48a86238c2dd12977b8bcd0c459c548b6a5eeb7330ba0f433d
|
File details
Details for the file simdlib-0.1.1-cp313-cp313-macosx_10_13_universal2.whl.
File metadata
- Download URL: simdlib-0.1.1-cp313-cp313-macosx_10_13_universal2.whl
- Upload date:
- Size: 15.3 kB
- Tags: CPython 3.13, macOS 10.13+ universal2 (ARM64, x86-64)
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f01c2cc56168b15c6657290fd7f4e433fc3e88f62225bb431636d682950d867a
|
|
| MD5 |
cf89fde843f260b2738f76dc32608b38
|
|
| BLAKE2b-256 |
cb1697e0c0b944353422744afc780bbe02920370648682a01b43cae543411b72
|