1. Static scheduling. - In the static scheduler I have implemented the video loading class also Each thread processes slices using a deterministic rule. A common static rule is block partitioning: start=tid×slides/k end=(tid+1)×slices/k The last thread handles any remainder slices. 2. Dynamic Using 1 work and a mutex to control serialization while (true) 3. Chunk Threads take groups of tasks instead of single tasks. /* take CHUNK slices instead of one process them repeat */ 4. Chunk Scheduling /*Chunk steal is work steal with the difference of (s / CHUNK) % k (group of chunks instead of s%k assigned to each queue /*elow is the chunk-stealing scheduler version of your program. Chunk stealing combines: chunk scheduling -> threads process groups of slices work stealing -> idle threads steal chunks from others Each thread has a local deque of chunks. When its queue is empty it steals a chunk from another thread. 5. Guided scheduler: Threads do not receive a fixed number of slices in advance. Instead, whenever a thread becomes free, it enters a critical section and checks how many slices remain unassigned. It then takes a chunk whose size is based on the remaining work: chunk = remaining / k where: - remaining = slices - next_slice - k = number of threads This means: - at the beginning, when many slices remain, threads take larger chunks - later, when fewer slices remain, chunk sizes become smaller - near the end, each thread may take just 1 slice This reduces scheduling overhead compared to fully dynamic scheduling (one slice at a time), while still improving load balance compared to pure static scheduling. Each claimed slice is processed row by row: - get pointer to the row in row-major memory - wrap it in row - apply quick_sort on that row ----------------------- ADAPTIVE SCHEDULERS 6. Adaptive --> See comments in code 7. ADDIDIVE INCREASE MULTIPLICATIVE DECREASE -- >See comments in code