Parallel Iterators for Python 3.14+ Free-Threaded Mode - High-performance parallel iteration inspired by Rust's Rayon
Project description
⚡️ FastIter
Parallel iterators for Python 3.14+ that actually work
2-5x faster processing for large datasets using Python's new free-threaded mode.
from fastiter import par_range
# Process 3 million items in parallel - 5.6x faster!
result = par_range(0, 3_000_000).map(lambda x: x * x).sum()
Why FastIter?
- ✅ Real speedups: 2-5.6x faster on CPU-bound work
- ✅ Drop-in replacement: Familiar iterator API
- ✅ No GIL: Takes advantage of Python 3.14's free-threaded mode
- ✅ Production ready: 40 tests, comprehensive docs
Installation
pip install fastiter
uv add fastiter
Requirements: Python 3.14+ (free-threaded build recommended)
Quick Start
from fastiter import par_range, into_par_iter, set_num_threads
# Configure threads (optional, auto-detects CPU count)
set_num_threads(4)
# Process ranges in parallel
total = par_range(0, 1_000_000).sum()
# Chain operations
evens = (
par_range(0, 10_000)
.filter(lambda x: x % 2 == 0)
.map(lambda x: x ** 2)
.collect()
)
# Work with lists
data = list(range(100_000))
result = into_par_iter(data).map(lambda x: x * 2).sum()
Performance
Measured on 10-core system with Python 3.14t (GIL disabled):
| Threads | Simple Sum (3M items) | CPU-Intensive Work |
|---|---|---|
| 2 | 1.9x | 1.9x |
| 4 | 3.7x | 2.3x |
| 8 | 4.2x | 3.9x |
| 10 | 5.6x | 3.7x |
Sweet spot: 4 threads for balanced performance
When to use FastIter
✅ Works great:
- Large datasets (500k+ items)
- CPU-bound computations
- Simple numeric operations
- Pure functions without shared state
❌ Not recommended:
- Small datasets (<100k items) - overhead dominates
- I/O-bound operations - use
asyncioinstead - Heavy lambda usage - Python function call overhead
API
Create parallel iterators
par_range(start, stop, step=1) # Parallel range
into_par_iter(iterable) # Convert any iterable
Operations
.map(func) # Transform each element
.filter(predicate) # Keep matching elements
.sum() # Sum all elements
.count() # Count elements
.min() / .max() # Find min/max
.any() / .all() # Test predicates
.reduce(id, op) # Custom reduction
.collect() # Gather to list
.for_each(func) # Execute function on each
Configuration
from fastiter import set_num_threads
set_num_threads(4) # Set thread count
# Or: export FASTITER_NUM_THREADS=4
Examples
CPU-intensive work (where FastIter shines):
def expensive_computation(x):
result = x
for _ in range(20):
result = (result * 1.1 + 1) % 1000000
return int(result)
# 3.9x faster with 8 threads
result = par_range(0, 200_000).map(expensive_computation).sum()
Simple aggregations:
# Sum of squares
total = par_range(0, 1_000_000).map(lambda x: x * x).sum()
# Count evens
count = par_range(0, 1_000_000).filter(lambda x: x % 2 == 0).count()
# Find maximum
maximum = into_par_iter([1, 5, 3, 9, 2]).max()
Complex pipelines:
result = (
par_range(0, 1_000_000)
.filter(lambda x: x % 2 == 0)
.map(lambda x: x * x)
.filter(lambda x: x > 1000)
.sum()
)
How It Works
FastIter uses a divide-and-conquer approach inspired by Rust's Rayon:
- Split: Data is recursively divided into chunks
- Distribute: Chunks are processed across threads
- Reduce: Results are combined back together
Key innovation: Adaptive depth limiting prevents thread pool exhaustion while maximizing parallelism.
Benchmarks
Run your own benchmarks:
# Full benchmark suite
uv run --python 3.14t python benchmarks/benchmark.py
# Quick demo
uv run --python 3.14t python main.py
# Run tests
uv run --python 3.14t pytest tests/ -v
Architecture
fastiter/
├── protocols.py # Producer/Consumer abstractions
├── core.py # ParallelIterator with 15+ operations
├── bridge.py # Work distribution (adaptive depth limiting)
├── consumers.py # Map, Filter, Reduce, etc.
└── producers.py # Range, List, Tuple data sources
See GUIDE.md for implementation details.
Requirements
Python 3.14+ with free-threaded mode for best performance:
# Check if you have the right Python
python3.14t --version
# Should show: Python 3.14.x free-threading build
# Verify GIL is disabled
python3.14t -c "import sys; print('GIL disabled:', not sys._is_gil_enabled())"
Contributing
We welcome contributions! See CONTRIBUTING.md for:
- Development setup
- Code style guidelines
- How to add new operations
- Testing requirements
License
MIT License - see LICENSE
Inspiration
- Rayon - Rust's data parallelism library
- PEP 703 - Making the GIL optional
- Tutorial - Implementing parallel iterators
Version
v0.1.0 - Production ready
- 40 passing tests
- 2-5.6x measured speedups
- Complete documentation
Made with ❤️ for high-performance Python
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 fastiter-0.1.0.tar.gz.
File metadata
- Download URL: fastiter-0.1.0.tar.gz
- Upload date:
- Size: 34.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4ff27499db9decec16efa787de25dd2290310820d1506525e8600c8b70787200
|
|
| MD5 |
ed039df8982fa85b19545d4a04409215
|
|
| BLAKE2b-256 |
e6358b096f1694c19d255dd8b5fc6ab736364610ef53faaec6726149058f03d0
|
Provenance
The following attestation bundles were made for fastiter-0.1.0.tar.gz:
Publisher:
publish.yml on rohaquinlop/fastiter
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fastiter-0.1.0.tar.gz -
Subject digest:
4ff27499db9decec16efa787de25dd2290310820d1506525e8600c8b70787200 - Sigstore transparency entry: 956061158
- Sigstore integration time:
-
Permalink:
rohaquinlop/fastiter@f68feb8c10dd6a2793160373d441567ded30e8f9 -
Branch / Tag:
refs/tags/0.1.0 - Owner: https://github.com/rohaquinlop
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f68feb8c10dd6a2793160373d441567ded30e8f9 -
Trigger Event:
release
-
Statement type:
File details
Details for the file fastiter-0.1.0-py3-none-any.whl.
File metadata
- Download URL: fastiter-0.1.0-py3-none-any.whl
- Upload date:
- Size: 16.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
625ae9c84615d8b2dd2d10117464f2a97c945623e3ac706d93bb9abeab118267
|
|
| MD5 |
5d1fee5121b58025f1e312cda2fc503f
|
|
| BLAKE2b-256 |
b50ff6ccc63e80ab2df6f4f9c0e2f4626cd405e2292433a665ea81a897e0c322
|
Provenance
The following attestation bundles were made for fastiter-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on rohaquinlop/fastiter
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fastiter-0.1.0-py3-none-any.whl -
Subject digest:
625ae9c84615d8b2dd2d10117464f2a97c945623e3ac706d93bb9abeab118267 - Sigstore transparency entry: 956061161
- Sigstore integration time:
-
Permalink:
rohaquinlop/fastiter@f68feb8c10dd6a2793160373d441567ded30e8f9 -
Branch / Tag:
refs/tags/0.1.0 - Owner: https://github.com/rohaquinlop
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f68feb8c10dd6a2793160373d441567ded30e8f9 -
Trigger Event:
release
-
Statement type: