Skip to main content

Parallel async primitives: fold, unfold, map, filter, and sorting

Project description

parfold

Parallel async primitives for tree-based operations: fold, unfold, map, filter, and sorting.

Why?

When you need to process many items with async functions (like LLM calls), sequential execution is slow. parfold provides tree-structured parallelism that achieves O(log n) depth instead of O(n).

# Sequential: O(n) round trips
result = items[0]
for item in items[1:]:
    result = await combine(result, item)

# Parallel fold: O(log n) round trips
from parfold import fold
result = await fold(items, combine)

Installation

pip install parfold

Primitives

fold — parallel tree reduction

Combines a list into a single result using parallel binary tree reduction.

from parfold import fold

async def combine(a: str, b: str) -> str:
    # Your async combining logic (e.g., LLM call)
    return await summarize_together(a, b)

chunks = ["chunk1", "chunk2", "chunk3", "chunk4"]
summary = await fold(chunks, combine)

How it works: Instead of combining left-to-right, fold pairs items and combines each pair in parallel, then pairs the results, and so on. For 8 items, that's 3 levels of parallelism instead of 7 sequential operations.

unfold — parallel tree expansion

Expands a seed into leaves by recursively decomposing, with all children expanded in parallel.

from parfold import unfold

async def decompose(query: str) -> list[str]:
    if is_specific_enough(query):
        return []  # Leaf node
    return await generate_subqueries(query)

specific_queries = await unfold("broad research question", decompose)

map — parallel transform

Applies an async function to each item in parallel.

from parfold import map

results = await map(items, async_transform)

filter — parallel predicate

Keeps items where the async predicate returns True.

from parfold import filter

relevant = await filter(items, async_is_relevant)

Sorting

Sorting algorithms using async comparison functions:

from parfold import quicksort, mergesort

async def compare(a, b) -> int:
    # Return negative if a < b, positive if a > b, 0 if equal
    return await llm_compare(a, b)

sorted_items = await quicksort(items, compare)
# or
sorted_items = await mergesort(items, compare)

Quicksort parallelizes comparisons to the pivot within each partition. Mergesort parallelizes the recursive sorting of left/right halves.

BST — Binary Search Tree

Lock-free BST with parallel inserts and O(1) sorted traversal.

from parfold import BST

async def compare(a: str, b: str) -> int:
    return await llm_compare(a, b)

tree = BST(compare)

# Parallel inserts
await asyncio.gather(*[tree.insert(x) for x in items])

# O(1) access to sorted order (no comparisons needed)
for item in tree:
    print(item)

# O(1) min/max
print(tree.min, tree.max)

Uses optimistic concurrency control for parallel inserts. Maintains a threaded linked list through nodes for cheap traversal.

Operation Comparisons Time
insert() O(log n) O(1) pointer ops
min/max 0 O(1)
for x in tree 0 O(n)
contains() O(log n)

CachedCompare

Wrap your comparison function to cache results:

from parfold import BST, CachedCompare

cached = CachedCompare(llm_compare)
tree = BST(cached)

# After operations:
print(f"Cache: {cached.hits} hits, {cached.misses} misses")

Use Cases

  • Summarization: Fold document chunks into a single summary
  • Search: Fold chunks while filtering by relevance to a query
  • Research expansion: Unfold a broad question into specific searches
  • Ranking: Sort items using LLM-based comparison
  • Clustering: Fold items into groups using LLM-based merging

Requirements

  • Python 3.10+
  • No dependencies (just asyncio)

License

MIT

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

parfold-0.1.3.tar.gz (17.6 kB view details)

Uploaded Source

Built Distribution

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

parfold-0.1.3-py3-none-any.whl (9.1 kB view details)

Uploaded Python 3

File details

Details for the file parfold-0.1.3.tar.gz.

File metadata

  • Download URL: parfold-0.1.3.tar.gz
  • Upload date:
  • Size: 17.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for parfold-0.1.3.tar.gz
Algorithm Hash digest
SHA256 81ae645ed44dc83637ca3f2664a5d474b13f35e501e4bbb31cf92278fbc9d039
MD5 3534f3f1aece60a3ae96c397f4dac595
BLAKE2b-256 ba96815c9fecca1ed584b697510bd989bf3142f8638f0a30e3700e9debfab803

See more details on using hashes here.

Provenance

The following attestation bundles were made for parfold-0.1.3.tar.gz:

Publisher: publish.yml on doublewordai/parfold

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file parfold-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: parfold-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 9.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for parfold-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 f07aa1c947c9c906ddac48c8fbe456707f8e8f35a536a7a1e8f438d9ea5610cf
MD5 cd9765c479106ae832e79b3ee8cb0dab
BLAKE2b-256 b56e5cd34c67e442579c011f1175abfd4f54f5f060c7787a48c7bd9cecd3e891

See more details on using hashes here.

Provenance

The following attestation bundles were made for parfold-0.1.3-py3-none-any.whl:

Publisher: publish.yml on doublewordai/parfold

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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