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.2.tar.gz (17.1 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.2-py3-none-any.whl (8.6 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: parfold-0.1.2.tar.gz
  • Upload date:
  • Size: 17.1 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.2.tar.gz
Algorithm Hash digest
SHA256 7700b6463bc33b313add52090c8faa6a3c91dd958b9618a1f76d2b5f2a47e8d8
MD5 e8f8131ec8678ddca3c6a2e4f8a865c4
BLAKE2b-256 e093309a41260e630f493c8e33453775a2d1161cbdff1ec4ec150e949e095285

See more details on using hashes here.

Provenance

The following attestation bundles were made for parfold-0.1.2.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.2-py3-none-any.whl.

File metadata

  • Download URL: parfold-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 8.6 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.2-py3-none-any.whl
Algorithm Hash digest
SHA256 92279c2c21384fdf8976a17dee98399575e10b50d242fbf3a89496ee872b1fb5
MD5 574295099e8c9d32da5932d1c4052b1e
BLAKE2b-256 68547948e028e46a5e4762b116eeb9f742f14bd3cd062c2e8c404b53df6d1ebb

See more details on using hashes here.

Provenance

The following attestation bundles were made for parfold-0.1.2-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