
Explore the basics of parallel computing, including von Neumann architecture, processes, threads, context switching, and parallelism concepts. Differentiate concurrency from parallelism and compare task-level versus data-level parallelism across multi-core systems.
In this quiz we are going to explore parallel programming in general
Launch three threads from the main thread to run function a, function b, and a test function, printing hello messages and determining the finish order including the main thread.
Demonstrate risks of passing a reference to a variable across threads, showing how detaching a thread can outlive object lifetimes and trigger access violations; advocate passing by value instead.
Explore invariants in doubly linked lists and how broken invariants during updates create race conditions. Learn to prevent them with mutexes.
Explore how condition variables and futures synchronize threads through a bus travel analogy, modeling arrival, distance, and wake-up behavior with threads that drive, stay awake, or nap.
Demonstrate how a condition variable coordinates a driver and a passenger using unique_lock, wait with a lambda condition, and notify_one, handling destination arrival and possible spurious wakeups.
Explore asynchronous operations with std::async, including launch policies (async, deferred, or both) and futures that return results from addition and subtract functions and a print task.
Implement parallel accumulate using asynchronous tasks and futures, dividing input into two parts with a minimum element count of 1000 to avoid oversubscription, and processing with std::async.
Learn how std::promise and std::future enable cross-thread value transfer, with set_value signaling readiness and future waiting, illustrated by a main thread and a print thread and a deadlock caution.
Explore parallel STL in C++17, comparing parallel and sequential algorithms, and learn to apply execution policies (par, seq, par_unseq) to operations like sort, with performance considerations and implementation details.
Explore parallel quicksort in modern c++ by implementing a sequential version first, then parallelizing a recursive call with std::async and future, using pivot, partition, and combining parts.
Implement a parallel find algorithm by dividing input into blocks, using a global atomic flag and a promise or async tasks to stop other threads once a match is found.
Explore how to implement parallel matrix operations in C++ by leveraging data independence. Learn about matrix multiplication and transpose stored in a row-major, single-dimensional array and how to parallelize them.
Implement a parallel matrix multiply by dividing the output data into start-end chunks processed by multiple threads, then compare performance against the sequential version.
Learn to implement a parallel matrix transpose in C++ using a sequential baseline, index flipping, and workload division across threads, with performance tradeoffs as matrix size grows.
Discover jthread, a C++20 thread that manages its life cycle and supports interruption via stop tokens, avoiding explicit join or detach.
Explore the basics of C++ coroutines in C++20, including await, suspend, and lazy generators; learn how coroutine objects, heap and stack state, and resume mechanics enable non-blocking, on-demand computation.
Explore c++ coroutines by defining a promise type, a coroutine handle, and a coroutine state object, then control suspension and resume execution with ko await and suspend always.
Explore how C++20 stop_callback registers a callback with a stop token to wake blocked threads via a synchronously fired lambda, using RAII and immediate firing for stopped tokens.
demonstrates a cancellable multistage pipeline in c++20 using bounded channels, semaphores, and a stop token to safely propagate end signals and apply back pressure from producer to filter to consumer.
Examine std::atomic_flag, the simplest atomic type representing a boolean value, and initialize atomic_flag variables with the atomic flag in it, then use test_and_set and clear to observe previous values.
Explore atomic pointers in C++ concurrency, where the pointer is atomic, not the pointed object, and apply is_lock_free, load, store, compare_exchange_weak, fetch_add, and fetch_sub.
Explore memory order relaxed and its lack of inter-thread guarantees, showing how writer and reader can see updates out of order and z may stay zero, unlike sequential consistency.
Understand how memory_order_acquire and memory_order_release govern synchronization and visibility of shared state, and why release-acquire pairs require preceding statements to be visible across threads.
Explore the transitive property of synchronization using three threads. Thread one populates an array, thread two uses release and acquire, and thread three observes the data.
Explain the release sequence on an atomic variable, showing how a writer's store with release and readers' loads with acquire establish synchronization points through read modify write operations.
Implement a Spinlock mutex using an atomic flag with test_and_set (memory order acquire) and clear (memory order release) to provide mutual exclusion, demonstrated with a lock guard and two threads.
This lecture introduces atomic ref, wrapping a reference to a non-atomic object to enable atomic access without changing structure layout, using load, store, and fetchAdd with relaxed ordering.
Explore a lock-free stack implemented with a simple singly linked list, detailing push and pop operations, LIFO behavior, race conditions, and atomic compare-exchange to update the head in multithreaded scenarios.
Explore hazard pointers to reclaim memory in a lock-free stack, detailing hazard pointer management, to-be-deleted lists, and safe node reclamation in a concurrent setting.
Enhances a thread pool by making submit return a future for a packaged task, enabling the calling thread to wait for task completion via futures with a move-only function wrapper.
Install the Cuda toolkit on your Nvidia gpu by checking compute capability and microarchitecture, verify with nvcc, and set up a Visual Studio Cuda project to run your first kernel.
Compute a unique global index for each thread in a one-dimensional CUDA grid by adding an offset equal to block id x multiplied by blockdim.x, enabling access to array elements.
Learn how to compute unique global indices for a two-dimensional grid by adding row offsets and block offsets to the thread id, ensuring all 16 elements are accessed.
Measure CPU and GPU execution times in CUDA programs by capturing clock cycles, translating to seconds; compare transfers, kernel time, and tune block size via trial and error.
Handle runtime errors in CUDA by checking each CUDA API call, using cudaGetErrorString for messages, and applying a file-and-line macro for centralized error reporting.
Explore how to query and print CUDA device properties across compute capabilities, including memory, threads per block, grid size, shared memory, and warp size, using cudaGetDeviceCount and cudaGetDeviceProperties.
C++ programming language can be categorized under many topics. Some say its a general purpose programming language, some say its a object oriented version of C. But I liked to categorized it under system programming language. One characteristic of any system programming language including C++ is that language should be able to execute faster compare to other languages like java etc.
C++ paradigm took sharp turn with the introduction of C++11 standards. The most notable difference with previous version is the introduction of new memory model. Memory model is the key part of any language, and the performance of all the functionalities depends on that language memory model. With new c++ memory model, we can exploit tremendous power of modern multi core processors.
Programming a proper C++ code with better memory reclaim mechanism is tough task. But if we want to code thread safe code which can harvest underline processors true power is much more difficult task. In this course we will have in depth discussion on C++ concurrency features including memory model. We will implements thread safe data structures and algorithms, both lock based manner and lock free manner. Proper lock free implementations of data structures and algorithms will provide unprecedented performance output. Let me listed down key aspects we cover in this course below.
1.Basics of C++ concurrency(threads, mutex, package_task, future ,async, promise)
2.Lock based thread safe implementation of data structures and algorithms.
3.C++ memory model.
4.Lock free implementation of data structures and algorithms.
5.C++20 concurrency features.
5. Proper memory reclaim mechanism for lock free data structures.
6. Design aspects of concurrent code.
7. In depth discussion on thread pools.
8. Bonus section on CUDA programming with C and C++.