PyODPS supports both asynchronous and parallel execution for immediate methods (execute, persist, head, tail, to_pandas).
Asynchronous Execution
Pass async_=True to an immediate method. It returns a concurrent.futures.Future object. Use .result() to wait for and retrieve the result.
Parallel Execution
Pass n_parallel=N to execute() to specify the concurrency level. This is effective when a DataFrame's execution depends on multiple cached DataFrames that can be computed in parallel.
Delay API (Optimized Parallelism)
To avoid redundant computations when multiple expressions share common dependencies, use the Delay API. You register operations with a Delay object and then call delay.execute(n_parallel=N). This automatically identifies common dependencies and executes them once before running the dependent tasks in parallel.
# Asynchronous execution
future = iris[iris.sepal_width < 10].head(10, async_=True)
print(future.result())
# Parallel execution with multiple dependencies
expr1 = iris.groupby('category').agg(value=iris.sepal_width.sum()).cache()
expr2 = iris.groupby('category').agg(value=iris.sepal_length.mean()).cache()
expr = expr1.union(expr2)
future = expr.execute(n_parallel=2, async_=True, timeout=2)
print(future.result())
# Using the Delay API for optimized dependency management
from odps.df import Delay
delay = Delay()
df = iris[iris.sepal_width < 5].cache() # Common dependency
# These return futures immediately without executing
future1 = df.sepal_width.sum().execute(delay=delay)
future2 = df.sepal_width.mean().execute(delay=delay)
# Trigger execution with specified concurrency
delay.execute(n_parallel=3)
print(future1.result())