Unit V — Applications of Parallel Computing

Big Data & Parallel Processing

Session 14 • 2311CSC501J — Hadoop, MapReduce & Spark

What You'll Learn

  • Why some data is too big for any one machine
  • Hadoop = HDFS + MapReduce + YARN
  • Map → Shuffle → Reduce, traced end-to-end
  • Why Spark's in-memory model is 10–100× faster

"Move the computation to the data, not the data to the computation."

— The one idea behind big data

Too Big For One Machine

This whole course, we made one machine faster

Google, 2004: index the entire web — petabytes across thousands of disks. No computer you can buy holds that. Disks fail, machines crash. So how do you process it?

Scale UP (old way)

Buy a bigger machine. Stops working — the biggest box still isn't big enough, and it's absurdly expensive.

Scale OUT (the answer)

Buy a thousand cheap machines and make them cooperate. This session is how.

Move the Code, Not the Data

1,000 GB of logs on 100 machines (10 GB each). You want to count something across all of it.

Move data → code

Copy all 1,000 GB over the network to one big machine. The network is the slowest thing in the building. Dead on arrival.

Move code → data

Send your 5 KB program OUT to all 100 machines. Each processes its own local 10 GB. Only the tiny result comes back. This scales.

Data locality: run the computation where the data already lives. A program is kilobytes; the data is terabytes — always move the small thing.

This is just data parallelism (Session 01) — but the "cores" are now whole machines.

Hadoop: The Full Stack

Open-source (2006), built from two Google papers. Three parts — storage, compute, scheduling.

Layer Name Job
StorageHDFSStore one giant file, split + replicated across many machines
ComputeMapReduceThe model + engine that runs your job in parallel across the cluster
Resource mgmtYARNThe scheduler — decides which machine runs which task

That's the whole stack. Everything else is detail. YARN even tries to place each task on the machine that already holds its data — data locality, automatically.

HDFS: Split & Replicate

HDFS chops a huge file into blocks (~128 MB) and keeps 3 copies of each on different machines.

A 512 MB file in HDFS   (4 blocks, replication factor 3)

           Block 1     Block 2     Block 3     Block 4
 Node A      [B1]                    [B3]
 Node B      [B1]        [B2]                    [B4]
 Node C                  [B2]        [B3]
 Node D      [B1]        [B2]                    [B4]
 Node E                              [B3]        [B4]

 Every block lives on 3 machines.  A disk dies -> the data survives.

Why replicate? In a cluster of thousands of cheap machines, something is always broken. With 3 copies, a dead disk is a non-event — Hadoop reads another copy and quietly makes a fresh third one.

At this scale, fault tolerance isn't a feature. It's survival.

MapReduce: Just Two Functions

You write only map and reduce. The framework does all the parallelism, distribution, and failure recovery for free.

INPUT --> MAP (parallel) --> SHUFFLE & SORT --> REDUCE (parallel) --> OUTPUT
          emit (k,v)         group by key        combine per key

Map

Each record → (key, value) pairs. Runs in parallel on every chunk. Data-parallel.

Shuffle & Sort

Framework groups all values by key across the cluster. The network-heavy step.

Reduce

One key + all its values → combine. Runs in parallel. The reduction from S03/S10.

The restriction IS the point: every job has the same shape, so the framework solves the hard distributed-systems problems once, for everyone.

Word Count, Traced End-to-End

Input: "the cat sat the mat the cat" — the "hello world" of MapReduce.

1) SPLIT       Mapper 1: "the cat sat the"     Mapper 2: "mat the cat"

2) MAP         M1: (the,1)(cat,1)(sat,1)(the,1)   M2: (mat,1)(the,1)(cat,1)
               (just tag each word with a 1 -- no counting yet)

3) SHUFFLE     cat -> [1,1]     mat -> [1]     sat -> [1]     the -> [1,1,1]
   & SORT      (group every pair by its key)

4) REDUCE      cat -> 2         mat -> 1       sat -> 1       the -> 3
               (sum the list of 1s per word)

   OUTPUT      cat 2   mat 1   sat 1   the 3

The magic: the exact same two functions work on one sentence or on ten petabytes across 5,000 machines. You wrote map & reduce; the framework did everything else. (See the 01-mapreduce-wordcount demo.)

Worked Example: The Shuffle Is the Whole Cost

Word count on 1 TB of text — roughly 170 billion words — across 1,000 mappers. The map and reduce functions are trivial. So where does the time go?

WITHOUT a combiner:

  map emits ("the",1) ("the",1) ("the",1) ... once per word occurrence
  intermediate pairs: 170,000,000,000
  at ~12 bytes each:  ~2 TB must cross the network in the shuffle

WITH a combiner (aggregate locally before sending):

  each mapper emits ("the", 4,213,905) — ONE pair per distinct word
  ~1,000,000 distinct words x 1,000 mappers x 12 bytes
                      ~12 GB crosses the network
Stage No combiner With combiner
Read 1 TB from HDFS (local disks, parallel)~100 s~100 s
Map: split into words~60 s~60 s
Shuffle across the network~2,000 s~12 s
Reduce: add up the counts~20 s~5 s
Total~36 minutes~3 minutes

Without a combiner, 92% of the job is the shuffle. The actual counting — the thing the program is for — is a rounding error. Everything else is moving data between machines.

A combiner is just your reducer, run on the mapper's own output before it leaves the machine. Usually one line:

job.setCombinerClass(SumReducer.class);   // the same class as the reducer

One line, 12× faster job. That is the highest-leverage line of code in this entire unit.

The catch, and it's a real one: a combiner is only valid if your reduce operation is associative and commutative — if combining in any grouping gives the same answer.

Operation Combiner safe?
sum, count, min, maxYes — grouping never changes the answer
averageNo! avg(avg(1,2), avg(3,4,5)) ≠ avg(1,2,3,4,5). Emit (sum, count) pairs instead and divide at the very end.
median, distinct countNo — need the full set (or an approximate algorithm like HyperLogLog)

The average trap catches people constantly, and it produces plausible-looking wrong numbers rather than an error. Notice it's the same associativity requirement as OpenMP's reduction clause in Session 03 — same maths, three units and a thousand machines apart.

Watch: MapReduce Explained

Watch someone else run the same map → shuffle → reduce trace. Repetition locks it in.

The only two functions you write are map and reduce. The framework handles the split, the shuffle, the parallel execution, and recovery when a machine dies.

Hadoop's Flaw: The Disk

MapReduce writes to disk between every step. Map → disk. Shuffle reads disk. Reduce → disk.

An iterative job (e.g. 3 passes over the data):

  DISK -> Map -> Reduce -> DISK -> Map -> Reduce -> DISK -> Map -> Reduce -> DISK
          '--- full disk round-trip between every stage -- the killer ---'

For one pass, fine. But most analytics — and all machine learning — loop over the same data 20–30 times. That's 30 rounds of writing gigabytes to disk and reading them back. The job crawls.

Recall Unit II: RAM is roughly 100× faster than disk. That number is about to become the whole plot.

Apache Spark: Keep It In Memory

Keep the working data in RAM across steps instead of writing to disk between stages. RAM is ~100× faster → 10–100× faster than Hadoop on iterative jobs.

Spark, the same iterative job:

  DISK -> [ load once ]  Map -> Reduce -> Map -> Reduce -> Map -> Reduce  -> DISK
                         '------- all in memory, no disk between -------'

RDD

Dataset split across the cluster's memory; rebuildable if a machine dies. Wrapped by DataFrames (a distributed SQL table).

Lazy DAG

Transformations build a task graph (S07); Spark optimizes the whole plan, then runs only when you ask for a result.

Same model

Still map & reduce underneath — minus the disk trips, plus a far nicer API.

Worked Example: Why Spark Won (Honestly)

Run 10 iterations of an algorithm like PageRank or k-means over a 100 GB dataset. Per iteration: 10 s of computing, and 100 GB to move.

Hadoop MapReduce Spark
Iteration 1: read the data60 s from disk60 s from disk
Iteration 1: compute10 s10 s
Iteration 1: write the result60 s back to HDFS0 — kept in RAM
Each of iterations 2–10130 s (read + compute + write)~12 s (RAM + compute)
Total for 10 iterations1,300 s ≈ 22 min178 s ≈ 3 min

7× faster — and notice Spark's computation is not faster at all. Both do 10 seconds of arithmetic per iteration. Spark wins entirely by not writing the intermediate result to disk and reading it straight back, nine times over.

Hadoop's model has no memory between jobs: every MapReduce job begins by reading HDFS and ends by writing HDFS. That was a deliberate 2004 choice — it makes fault tolerance almost free, because every intermediate result is already durable on disk. A fine trade for one job. Ruinous for ten in a loop.

About the "100× faster than Hadoop" on Spark's website — be sceptical, and know exactly why. Look at the shape of it:

speedup  ~   (disk I/O + compute)  x  iterations
             ---------------------------------------
              one initial load  +  compute x iterations

The advantage grows with the number of iterations and shrinks as the compute per iteration grows. So:

  • 100 iterations, light compute → genuinely 50–100×. That's where the marketing number comes from, and it is real.
  • A single pass, heavy compute → roughly . For a one-shot ETL job Spark buys you nicer APIs, not speed.
  • Data larger than cluster RAM → Spark spills to disk and most of the advantage evaporates.

And here's what Spark had to invent to make RAM safe. If an intermediate result lives only in memory and a node dies, the data is simply gone. Spark's answer is lineage: it stores the recipe that produced each partition, not the partition. Lose one, and it recomputes just that one from its parents.

That's the elegant bit worth remembering: Hadoop gets fault tolerance by storing everything; Spark gets it by storing how to rebuild anything. Both are correct. One of them is seven times faster on a loop.

Spark vs Hadoop MapReduce

Dimension Hadoop MapReduce Apache Spark
Data between stepsWritten to diskKept in memory (RAM)
Speed (iterative)Baseline10–100× faster
APIJust map + reduce (verbose)SQL, DataFrames, Python, MLlib
EvaluationEager, stage by stageLazy — optimizes a DAG first
Best forHuge one-pass batch; low memoryIterative ML, interactive queries

The honest nuance: Hadoop isn't dead — HDFS is still a common storage layer, and giant single-pass jobs still suit MapReduce. But for iterative and interactive work, Spark won.

Where It Runs & Why It Matters

You rent a cluster; you don't build one

Twenty years of one idea

Google MapReduce paper (2004)  ->  Hadoop (2006)  ->  Spark (2014)  ->  cloud data platforms

               split the data  ->  map in parallel  ->  shuffle by key  ->  reduce in parallel
                          (getting faster and easier the whole way)

Map is data parallelism; reduce is the reduction. This is fan-out / fan-in — the same shape as an MPI Scatter → compute → Reduce, at data-center scale.

Quick Check: Is This a MapReduce Job?

The test: can you express it as independent work on each record, then grouped combining? Shout it out.

1. Count how many times each error code appears in 50 TB of logs

Perfect fit. Map → (code, 1). Reduce → sum. Combiner safe. This is word count wearing a different hat, and most real MapReduce jobs are.

2. Sort 100 TB of records

Yes — and famously so. Map partitions by key range, the shuffle does the global ordering, reduce sorts locally. Hadoop held the world sort record for years doing exactly this.

3. Train a neural network for 10,000 steps

Terrible fit. Every step depends on the previous one — 10,000 sequential job launches, each paying full HDFS round-trip. This exact pain is why Spark exists, and why AI training uses MPI-style all-reduce instead.

4. Find the median salary across 1 billion records

Possible, awkward. Median isn't associative — no combiner, so the full dataset shuffles. In practice you sort first, or accept an approximate answer. Some questions are just expensive to ask.

5. The one people get wrong: "Fetch one user's profile by ID, in under 10 ms"

Absolutely not — and this is the most valuable answer of the five. MapReduce launches JVMs, schedules containers and scans partitions; the startup alone is tens of seconds. It is a batch throughput engine, built to process petabytes over hours. For a single-record lookup you want a database index — a millisecond, on one machine.

Session 01's latency-versus-throughput distinction, one last time. Everything in Unit V buys throughput. None of it buys latency. Reaching for "big data" tooling on a small-data problem is one of the most expensive mistakes in the industry — and it's the same category error as the toll booth on day one.

Recap & What's Next

Key Takeaways

Homework

Next session: Real-Time Systems & Recent Trends (+ Course Wrap-Up)

Federated learning, the computing frontier, and tying the whole course together.