# Multi-tasking: Foundation

* * *

Let's first understand which tasks are CPU-Intensive and which are I/O bound.

### CPU-Intensive Tasks

> These tasks require significant processing power and keep the CPU busy.

**Examples**

*   Mathematical calculations
    
*   Scientific simulations
    
*   Cryptography (encryption/decryption)
    
*   Data compression and decompression
    
*   Image processing and filtering
    
*   Video encoding/transcoding
    
*   Audio signal processing
    
*   Machine Learning model training
    
*   3D rendering and ray tracing
    
*   Game physics calculations
    
*   Sorting very large datasets in memory
    
*   Data analytics and statistical computations
    
*   Compiling source code
    
*   Bitcoin/cryptocurrency mining
    
*   Pathfinding algorithms (A\*, Dijkstra)
    
*   AI inference on large models
    

**Characteristics**

*   CPU utilization is usually high (80-100%).
    
*   Faster CPUs improve performance significantly.
    
*   <mark class="bg-yellow-200 dark:bg-yellow-500/30">Adding more CPU cores often helps through </mark> **<mark class="bg-yellow-200 dark:bg-yellow-500/30">parallelization</mark>**<mark class="bg-yellow-200 dark:bg-yellow-500/30">.</mark>
    
*   <mark class="bg-yellow-200 dark:bg-yellow-500/30">Threads may not help much in some languages due to runtime limitations (e.g., Python GIL).</mark>
    

### I/O-Bound Tasks

> These tasks spend most of their time waiting for data from external systems.

**Examples**

#### 1\. File System Operations

*   Reading large files
    
*   Writing files to disk
    
*   Uploading/downloading files
    

#### 2\. Database Operations

*   Executing SQL queries
    
*   Fetching records
    
*   Updating data
    

#### 3\. Network Operations

*   Calling REST APIs
    
*   GraphQL requests
    
*   Communicating with microservices
    
*   Downloading web pages
    

#### 4\. Cloud/External Services

*   Accessing Azure Storage
    
*   AWS S3 operations
    
*   Sending emails
    
*   Message queue processing (Kafka, RabbitMQ)
    

#### 5\. User Interaction

*   Waiting for user input
    
*   Form submission handling
    

**Characteristics**

*   CPU usage is often low.
    
*   Performance depends on disk, network, or database latency.
    
*   **<mark class="bg-yellow-200 dark:bg-yellow-500/30">Asynchronous programming</mark>** <mark class="bg-yellow-200 dark:bg-yellow-500/30">provides significant benefits.</mark>
    
*   Thousands of concurrent requests can be handled with relatively few threads.
    

👍 Quick Rule of Thumb

Ask yourself:

> **"Is the application busy calculating or busy waiting?"**

*   Busy **calculating** → CPU-bound
    
*   Busy **waiting** (database, API, disk, network) → I/O-bound
    

* * *

Now, let's understand the difference between concurrency and parallelism with the help of restaurant analogy.

### Concurrency (Interleaving): Taking Turns

Imagine you're a chef preparing two dishes:

*   Pasta 🍝
    
*   Soup 🍲
    

**What you do**

1.  Put soup on the stove.
    
2.  While it's boiling, chop vegetables for pasta.
    
3.  Stir the soup.
    
4.  Cook the pasta.
    
5.  Check the soup again.
    

Although you're working on **both dishes during the same time period**, you're only doing **one thing at a time**.

```plaintext
Time →
Soup:   Cook ---- Wait ---- Stir ---- Wait
Pasta:       Chop ---- Cook ---- Plate
```

This is **concurrency**. This is achieved using asynchronous coding.

**Key idea**

Multiple tasks are in progress, but they take turns sharing the same resource (you, the chef).

### Parallelism: Doing Things Literally at the Same Time

Now imagine there are **two chefs**.

*   Chef A cooks soup.
    
*   Chef B cooks pasta.
    

Both are actively working at the exact same moment.

```plaintext
Time →

Chef A: Cook soup ---------------
Chef B: Cook pasta --------------
```

This is **parallelism**.

**Key idea**

Multiple tasks are executing **simultaneously** using multiple workers (CPU cores, threads, machines, etc.).

Think of it this way:

**Concurrency = "Don't wait, do something else meanwhile"**

**Parallelism = "Actually execute multiple tasks at the same time"**

Note: - A system can be **concurrent without being parallel** (like Node.js handling many I/O requests on a single thread), and it can also be **both concurrent and parallel** (like a web server using multiple CPU cores to handle many requests simultaneously).

* * *

### Asynchronous programming in python is concurrent or parallel?

Asynchronous programming in Python (primarily using the `asyncio` library) is **<mark class="bg-yellow-200 dark:bg-yellow-500/30">concurrent, not parallel</mark>**.

It allows your program to manage and switch between **multiple tasks at the same time** (concurrency), but it executes those tasks using a single thread on a single CPU core, meaning they are **never running at the exact same physical instant** (parallelism).

**💡 Quick Comparison**

To understand the difference between how Python handles concurrency and parallelism, look at the three main approaches:

| Approach | Type | How it Works | Best Used For |
| --- | --- | --- | --- |
| Asyncio (Asynchronous) | 🔀 **Concurrent** | A single thread uses an **event loop** to switch tasks when one is waiting (cooperative multitasking). | I/O-bound tasks |
| Threading | 🔀 **Concurrent** | Multiple threads take turns on a single CPU, managed by the Operating System. | I/O-bound tasks |
| Multiprocessing | 🚀 **Parallel** | Spawns entirely separate processes across **multiple CPU cores** at the same time. | CPU-bound tasks |

* * *

Thank you for your time! 😊

Connect with me on [LinkedIn](https://www.linkedin.com/in/shubham-agrawal-9a0b2b120/)
