40 likes | 54 Vues
E81 CSE 532S: Advanced Multi-Paradigm Software Development. C++11 Atomic Types and Memory Model. Chris Gill Department of Computer Science and Engineering Washington University in St. Louis cdgill@cs.wustl.edu. Atomic Types. Many atomic types in C++11 STL, some are lock-free
E N D
E81 CSE 532S: Advanced Multi-Paradigm Software Development C++11 Atomic Types and Memory Model Chris Gill Department of Computer Science and Engineering Washington University in St. Louis cdgill@cs.wustl.edu
Atomic Types • Many atomic types in C++11 STL, some are lock-free • Always lock-free: std::atomic_flag • If it matters, must test others with is_lock_free() • Also can specialize std::atomic<> class template • This is already done for many standard non-atomic type • Can also do this for your own types that implement a trivial copy-assignment operator, are bitwise equality comparable • Watch out for semantic details • E.g., bitwise evaluation of float, double, etc. representations • Equivalence may differ under atomic operations
Reasoning about Concurrency • Operations on atomic types semantically well defined • Synchronizes-with relationship ensures that (unambiguously) operation X happens before or after operation Y • Can leverage this so eventually Xi happens-before Yj • Transitivity then lets you build various happens-before cases, including inter-thread happens-before relationships • Other variations on this theme are also useful • Dependeny-ordered-before and carries-a-dependency-to are used to reason about cases involving data dependencies • I.e., the result of one atomic operation is used in another
Memory Models and Design • Trading off stricter ordering vs. higher overhead • Sequential consistency is easiest to think about (implement) because it imposes a consistent global total order on threads • Acquire-release consistency relaxes that to a pair-wise partial order that admits more concurrency • Relaxed ordering is least expensive, but should be applied selectively where available to optimize performance • Even these basic constucts allow sophisticated design • Memory fences to synchronize otherwise relaxed segments • Release chains offer a similar idea for data dependencies • Mixing atomic operations in with non-atomic ones to reduce overhead, but still enforce correct semantics (Chapter 7)