Meetup

Python and Dask: Scaling the DataFrame

Dan Gerlanc, Enplus AdvisorsEpisode 25 · 1:28:56 · Jul 2020 · 268 viewsHosted by Demetrios Brinkmann
Thumbnail for Python and Dask: Scaling the DataFrame Watch on YouTube
TL;DR
  1. 1

    Dask scales familiar pandas-style DataFrame work across partitions, cores, and machines while keeping the computation in Python.

  2. 2

    Dask builds a lazy task graph and executes it only when you call compute, which lets it find opportunities for parallel work.

  3. 3

    Distributed computing adds coordination and data-transfer costs, so an in-memory pandas solution is usually faster when the data fits on one machine.

Summary

Dan Gerlanc gives a practical introduction to Dask DataFrames. He explains how Dask keeps the pandas mental model while splitting a logical DataFrame into smaller pandas DataFrames, or partitions, that can run across workers. Dask builds a directed acyclic graph of operations instead of executing each statement immediately. Calling compute schedules that graph, while persist keeps computed partitions in memory for later work. The workshop uses New York City payroll data to demonstrate reading multiple CSV files, inspecting partitions, calculating maxima, and grouping data. Dan also uses the Dask dashboard to show workers, task execution, waiting time, and data transfers. He compares Dask with Spark and PySpark, describing Dask as easier to start with for Python teams and more flexible for arbitrary Python functions. He is clear about the cost: distributed execution adds overhead, so data that fits in RAM should usually stay in memory.

Key ideas
06:03

Dask keeps the DataFrame model by partitioning pandas DataFrames

Dask DataFrames are made from multiple smaller pandas DataFrames. One larger logical DataFrame can be split into partitions in memory on one computer or across a cluster. The partitions provide the source of parallelism and let Dask work through data that is too large for one machine's memory. Dask handles the chunking, so users do not have to manually read, process, and combine one piece at a time. In the demonstration, Dask reads New York City payroll CSV files and creates three partitions by default, then creates 22 partitions when Dan sets a smaller block size of half a megabyte.

18:45

Dask delays execution by building a directed acyclic graph

A Dask operation creates a directed acyclic graph of functions rather than immediately producing a result. Reading a CSV creates separate read tasks for the partitions. Selecting a column and calculating its maximum adds more tasks to that graph. The independent file reads and per-partition maxima can run in parallel, while the final aggregation waits for those results. Dask only performs the work after the user calls compute. This lets the scheduler inspect the whole computation and find parallel work without the user describing how to divide it across workers.

12:05

Dask can run locally before it runs across a cluster

Dan starts Dask's distributed scheduler by importing the client and instantiating it. The same approach can create a local cluster on a laptop or connect to a larger cluster. In his example, the local setup exposes four workers, eight threads, and the laptop's available memory. Dask can also run through Binder, locally with JupyterLab, on HPC clusters, on existing YARN clusters, or across instances connected with SSH. Dan describes it as lightweight because it does not require HDFS or YARN, although those systems can be used when available.

21:16

compute performs the graph, while persist caches its partitions

Calling compute turns a lazy Dask graph into an answer and makes the scheduler execute its tasks. Dan points out that Dask does not automatically keep the data in memory. After showing the head of a DataFrame, a later maximum calculation reads the CSV again because the earlier result was not persisted. Calling persist tells Dask to keep the computed partitions in memory on the cluster. The resulting graph contains the in-memory partitions instead of the original file-reading tasks, so later calculations can start from those partitions.

33:02

Distributed execution is slower when the data already fits in memory

Dan compares pandas and Dask on the same kind of calculation. Pandas is fast after the data is loaded into memory, while Dask carries the extra cost of coordinating workers and serializing data. He says that a distributed solution should be used when it solves a real size or compute problem. If the dataset fits in RAM, the in-memory approach has less work to do. The Dask documentation describes parallelism and distributed computing as expensive ways to accelerate an application that could instead use memory, a faster algorithm, or compiled code.

43:33

Dask gives Python teams arbitrary functions and a simpler execution model than Spark

Dan contrasts Dask with PySpark and Koalas. Spark runs on the JVM and Python calls can involve a separate Python process with serialized data, while Dask is written in Python from the workers through the scheduler. Dask can use regular Python functions and integrate with pandas, NumPy, and scikit-learn. Its lower-level primitives give users more control than Spark's higher-level operators, although that flexibility can give the scheduler fewer obvious opportunities for optimization. Dan prefers starting with Dask when a team needs Python-based distributed processing and does not have Spark specialists.

01:12:14

The dashboard shows whether workers are computing or waiting

Dask's dashboard shows the task stream as a timeline. Each rectangle is an individual task, each color usually identifies a function, and each bar corresponds to a worker or execution thread. Filled areas show computation, while white space shows a worker waiting. Red areas indicate data transfer between workers. Dan uses the dashboard to explain why a computation can finish with one worker holding the final result after intermediate values move across the cluster. A graph with frequent gaps can mean the tasks are too small, because network and scheduling overhead takes longer than the computation.

01:20:48

Task size determines whether parallelism helps

Dan changes the chunk size of a random-array calculation to show poor worker utilization. If tasks are too small, workers finish quickly and spend most of their time waiting for the next task or transferring results. Adding two numbers is cheap compared with moving those numbers across the network, while summing a much larger batch can make the transfer cost worthwhile. The dashboard makes this visible through white space and data-transfer blocks. The practical point is to choose work units large enough to keep workers busy without creating partitions that are too large for available memory.

"Parallelism and distributed computing are expensive ways to accelerate your application that could otherwise be solved in memory or using a faster algorithm or compiled code."Dan Gerlanc39:59
Who should watch
  • You work with pandas DataFrames and need to process data that no longer fits comfortably in one machine's memory.
  • Your team wants Python-native distributed processing and does not have deep Spark expertise.
  • You need to understand why a distributed job is slow, especially when the dashboard shows waiting workers or heavy data transfer.