ITT 440 Network Programming - Chapter 9: Parallel Programming in Python

Thread vs Processes

  • Hyper-threading:
    • Intel's initial attempt to introduce parallel computation to consumer PCs.
    • First appeared in desktop CPUs with the Pentium 4 HT in 2002.
    • A single physical CPU core appears as two logical CPUs to the OS due to hyper-threading.
    • The actual CPU hardware has only one set of execution resources per core.
    • Hyper-threading enables the sharing of physical execution resources between logical CPU cores.
    • It enhances system speed, but not as effectively as having actual additional cores.
  • Multiple cores:
    • Original CPUs had a single core.
    • Manufacturers added more cores to increase performance.
    • A dual-core CPU has two central processing units, appearing as two CPUs to the OS.
    • A CPU with multiple cores can run different processes simultaneously, speeding up the system.
    • A dual-core CPU has two central processing units on the CPU chip.
    • A quad-core CPU has four, and an octa-core CPU has eight.
  • Core vs Hyper-threading
    • Hyper-threading deceives the OS into recognizing two CPUs for each core.
    • Multi-core CPUs have actual multiple processing units.
    • Modern CPUs have both multiple cores and hyper-threading.
    • A dual-core CPU with hyper-threading appears as four cores to the operating system.
    • Hyper-threading is not as effective as additional cores.
    • A dual-core CPU with hyper-threading performs better than one without.
  • How threads work:
    • A thread is a unit of execution within a process.
    • A process can have one or more threads.
  • How processes work:
    • Programs are stored on disk or in non-volatile memory in an executable form.
    • The program is loaded into the computer’s memory in binary form.
    • Executing programs require memory and OS resources.
    • A process is a program loaded into memory with all necessary resources.
  • Thread vs. Process:
    • Thread: Lighter weight operations; uses the memory of the process it belongs to. Inter-thread communication is faster. Context switching is less expensive. Threads share memory with other threads of the same process.
    • Process: Heavyweight operations; has its own memory space. IPC (Inter-Process Communication) is slow. Context switching is more expensive. Processes do not share memory.

Parallel vs Concurrent

  • Whether processes or threads can run at the same time depends on the system.
    • Multiple processors or CPU cores allow parallel execution.
    • A single processor shares CPU time among processes/threads via scheduling algorithms.
    • Parallelism and concurrency distinguish real vs approximate simultaneous operation.
  • Concurrency:
    • Concurrency: An application progresses on multiple tasks seemingly at the same time.
    • On a single-CPU system, tasks are not executed simultaneously, but multiple tasks are in progress.
    • The CPU switches between tasks during execution.
  • Parallel Execution:
    • Parallel execution: A computer with multiple CPUs/cores makes progress on multiple tasks simultaneously.
  • Parallel Concurrent Execution:
    • It's possible to have parallel concurrent execution.
    • Threads on the same CPU execute concurrently.
    • Threads on different CPUs execute in parallel.
  • Parallelism:
    • Parallelism: An application divides tasks into subtasks for parallel processing on multiple CPUs.
    • True parallelism requires multiple threads running on separate CPUs/cores/GPUs.
  • Concurrency & Parallelism Combination
    • Concurrent, Not Parallel: Progress on multiple tasks at the same time (seemingly).
    • Parallel, Not Concurrent: Works on one task at a time, broken into parallel subtasks.
    • Neither Concurrent Nor Parallel: Works on one task at a time, no subtasks.
    • Concurrent and Parallel: Application is both concurrent and parallel.

The Python Parallel Programming Ecosystem

  • The number of processes is limited by the number of processors.
    • cpu_count() function in multiprocessing module shows the processor count.
  • Synchronous Execution:
    • Synchronous execution completes processes in the order they were started.
    • This is achieved by locking the main program until processes finish.
  • Asynchronous Execution:
    • Asynchronous execution doesn't involve locking.
    • The order of results can be mixed up, but it's usually quicker.
  • Create a process which prints the assigned id
    • Subclass multiprocessing.Process to create an independent process.
    • Extend the __init__ method to initialize resources.
    • Implement the Process.run() method for the subprocess code.
  • To spawn the process, initialize the Process object and invoke Process.start().
    • Process.start() creates a new process and invokes the Process.run() method.
    • Code after p.start() executes immediately, before process p completes.
    • Use Process.join() to wait for task completion.
  • Pool Class:
    • Pool class can be used for parallel execution of a function for different input data.
    • The multiprocessing.Pool() class spawns a set of worker processes and can submit tasks using the methods apply/applyasync and map/mapasync.
    • For parallel mapping, you should first initialize a multiprocessing.Pool() object.
    • The first argument is the number of workers; if not given, that number will be equal to the number of cores in the system.
  • Concurrent Network Servers:
    • Server-type applications communicating with many clients require high concurrency and I/O performance.
    • A web server should handle hundreds of thousands of concurrent connections and service tens of thousands of requests per second.
    • Ideally, use threads to program the interaction with a single client and then lift this interaction to multiple clients by simply forking many instances of the single-client interaction in separate threads.
  • There are various ways to implement parallel processing using the general procedure and multitasking module.
    • Taking advantage of these benefits is the same for any size machine.
    • The result will gain speed, depending on the number of processors, when the procedures are followed exactly.
    • This is a beginning of knowledge of Parallel Programming which we started by using Python language.
    • In network programming this parallelism we can accomplish by using concurrent network server.