Skip to main content

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

simdlib-0.1.1.tar.gz (10.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

simdlib-0.1.1-cp313-cp313-macosx_10_13_universal2.whl (15.3 kB view details)

Uploaded CPython 3.13macOS 10.13+ universal2 (ARM64, x86-64)

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

Hashes for simdlib-0.1.1.tar.gz
Algorithm Hash digest
SHA256 3145266ae11c4d1e34a831461ce81a7b6d6881af41a42eac84f4236d73f13b56
MD5 28c84348f05607991f67ac7e175d0e98
BLAKE2b-256 0b39f728a20f9c48a86238c2dd12977b8bcd0c459c548b6a5eeb7330ba0f433d

See more details on using hashes here.

File details

Details for the file simdlib-0.1.1-cp313-cp313-macosx_10_13_universal2.whl.

File metadata

File hashes

Hashes for simdlib-0.1.1-cp313-cp313-macosx_10_13_universal2.whl
Algorithm Hash digest
SHA256 f01c2cc56168b15c6657290fd7f4e433fc3e88f62225bb431636d682950d867a
MD5 cf89fde843f260b2738f76dc32608b38
BLAKE2b-256 cb1697e0c0b944353422744afc780bbe02920370648682a01b43cae543411b72

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page