More foray inside the parallel programming
CNRS
IMAG
Paul-Valéry Montpellier 3 University
0.08\% = \frac{1}{16 * 2 (cores + hyperthreading) * \frac{256 (bitwide vector unit}{64(bit double)} = 128}
\frac{S_{up}}{T_{par}} \gg \frac{S_{up}}{T_{seq}}
Ratio of speedup improvment S_{up} over time of development (T_{seq|par}) comparison.
From a development time perspective, return on investment (speedup) is often several magnitudes of order better than pure “serial/sequential” improvment.
Simple “divide and conquer” strategies in parallel programming allow to handle data with previously almost untractable sizes and scale before.
Note
This is a huge one, in the present context 😬
Difficult to estimate but the Thermal Design Power (TDP), given by hardware manufacturers, is a good rule of thumb. Just factor the number of units, and usual proportionality rules.
Example of “standard” use : 20 16-core Intel Xeon E5-4660 which is 120~W of TDP
P = (20~Processors) * (120~W/~Processors) * (24~hours) = 57.60~kWhrs
A Tesla V100 GPU is of 300~W of TDP. Let’s use 4 of them.
P = (4~GPUs) * (300~W/~GPUs) * (24~hours) = 28.80~kWhrs
\Longrightarrow half of the power use
If P and S is the parallel (resp. serial) fraction of the code and N the number of computing units:
S_{up}(N) \le \frac{1}{S+\frac{P}{N}}
When the size of the problem grows up proportionnaly to the number of computing units.
S_{up}(N) \le N - S*(N-1)
where N is the number of computing units and S the serial fraction as before.
Strong scaling represents the time to solution with respect to the number of processors for a fixed total size.
Weak scaling represents the time to solution with respect to the number of processors for a fixed-sized problem per processor.
┌────────────────────────────────────┐
│ 1000 │
│ ┌───────────────────┐ │
│ │ │ │ 1 processor
│ │ │ │
│ │ │ │
│ 1000 │ │ │
│ │ │ │
│ │ │ │
│ └───────────────────┘ │
│ ┌─────────┐ ┌─────────┐ │
│ │ │ │ │ │
│ 500 │ │ │ │ │
│ │ │ │ │ │
│ └─────────┘ └─────────┘ │
│ 500 │ 4 processors
│ ┌─────────┐ ┌─────────┐ │
│ │ │ │ │ │
│ │ │ │ │ │
│ │ │ │ │ │
│ └─────────┘ └─────────┘ │
│ 250 │
│ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │
│ 250 │ │ │ │ │ │ │ │ │
│ └────┘ └────┘ └────┘ └────┘ │
│ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │
│ │ │ │ │ │ │ │ │ │
│ └────┘ └────┘ └────┘ └────┘ │ 16 processors
│ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │
│ │ │ │ │ │ │ │ │ │
│ └────┘ └────┘ └────┘ └────┘ │
│ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │
│ │ │ │ │ │ │ │ │ │
│ └────┘ └────┘ └────┘ └────┘ │
└────────────────────────────────────┘
┌───────────────────────────────────────────────────────────┐
│ 1000 │
│ ┌─────────┐ │
│ │ │ │
│ 1000 │ ───┼──┐ │
│ │ │ │ │
│ └─────────┘ │ │
│ 1000 │ │
│ ┌─────────┐ ┌────┼────┐ │
│ │ │ │ │ │ │
│ 1000 │ │ │ │ │ │
│ │ │ │ │ │ │
│ └─────────┘ └────┼────┘ │
│ ┌─────────┐ ┌────┼────┐ │
│ │ │ │ │ │ │
│ │ │ │ │ │ │
│ │ │ │ │ │ │
│ └─────────┘ └────┼────┘ │
│ │ 1000 │
│ ┌─────────┐ ┌─────────┐ ┌────┼────┐ ┌─────────┐ │
│ │ │ │ │ │ │ │ │ │ │
│ │ │ │ │ │ ▼ │ │ │1000 │
│ │ │ │ │ │ │ │ │ │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │ │ │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │ │ │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │ │ │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
└───────────────────────────────────────────────────────────┘
Simple Instruction | Multiple Instructions | |
---|---|---|
Simple Data | ||
Multiple Data |
Parallelism level | Hardware | Software | Parallelism extraction |
---|---|---|---|
Instruction | SIMD (or VLIW) | Intrinsics | Compiler |
Thread | Multi-core RTOS | Library or language extension | Partitioning/Scheduling (dependency control) |
Task | Multi-core (w/o RTOS) | Processes (OS level) | Partitioning/Scheduling |
Main Process
┌─────────────┐
│ │
│ CPU │
├─────────────┤
│ │
│ Memory │
└─┬────┬────┬─┘
│ │ │
│ │ │
┌───────────┘ │ └───────────┐
│ │ │
┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐
│ │ │ │ │ │
│ CPU │ │ CPU │ │ CPU │
├─────────────┤ ├─────────────┤ ├─────────────┤
│ │ │ │ │ │
│ Memory │ │ Memory │ │ Memory │
└─────────────┘ └─────────────┘ └─────────────┘
Process 1 Process 1 Process 1
┌──────────────────────────────────────┐
│ MAIN PROCESS │
│ │
│ │
│ ┌──────────┐ │
│ │ │ │
│ │ CPU │ ┌───────────┐ │
│ │ │ │ │ │
│ └──────────┘ │ Memory │ │
│ │ │ │
│ └───────────┘ │
│ │
│ │
│ │
│ ┌─┐ ┌─┐ ┌─┐ │
│ │┼│ │┼│ │┼│ │
│ │┴│ │┴│ │┴│ │
│ ▼▼▼ ▼▼▼ ▼▼▼ │
│ Thread 1 Thread 2 Thread 3 │
│ ┌─┐ ┌─┐ ┌─┐ │
│ │┼│ │┼│ │┼│ │
│ │┴│ │┴│ │┴│ │
│ ▼▼▼ ▼▼▼ ▼▼▼ │
│ │
└──────────────────────────────────────┘
Multi-processing | Multi-threading | |
---|---|---|
Memory | Exclusive | Shared |
Communication | Inter-process | At caller site |
Creation overhead | Heavy | Minimal |
Concurrency | At OS level | Library/language |
Advanced concepts in parallel programmingAdvanced Programming and Parallel Computing, Master 2 MIASHS