This is not the current version of the class.

Lecture 16: Synchronization goals, parameters, and MESI

Synchronization lectures

The next lectures concern synchronization. We’ll talk about how synchronization primitives, such as locks, are implemented; advanced schemes for synchronization that minimize overhead; and the properties of machines that make synchronization difficult and interesting. Although you could implement these ideas in your problem sets, you don’t need to.

Synchronization parameters

Simple test and set lock

struct spinlock {
    std::atomic_flag f_;

    void lock() {
        while (f_.test_and_set()) {
        }
    }
    void unlock() {
        f_.clear();
    }
};

Goals

Goals

Parameter: Contention

Parameter: Contention

Parameter: Granularity

Parameter: Granularity

Parameter: Write balance (write weight)

Parameter: Write balance

Write balance examples

Parameter: Thread count

Architecture

MESI

MESI

MESI transition examples

MESI consequences

Simple test and set lock

struct spinlock {
    std::atomic_flag f_;

    void lock() {
        while (f_.test_and_set()) {
        }
    }
    void unlock() {
        f_.clear();
    }
};

pause

pause — spin loop hint

Opcode  Mnemonic    Description
F3 90   PAUSE       Gives hint to processor that improves
                    performance of spin-wait loops.

Description
Improves the performance of spin-wait loops. When
executing a "spin-wait loop," a Pentium 4 or Intel Xeon
processor suffers a severe performance penalty when
exiting the loop because it detects a possible memory
order violation. The PAUSE instruction provides a hint to
the processor that the code sequence is a spin-wait loop.
The processor uses this hint to avoid the memory order
violation in most situations, which greatly improves
processor performance. For this reason, it is recommended
that a PAUSE instruction be placed in all spin-wait loops.

Paused test and set lock

struct spinlock {
    std::atomic_flag f_;

    void lock() {
        while (f_.test_and_set()) {
            pause();  // compiles to `pause`
        }
    }
    void unlock() {
        f_.clear();
    }
};

Yielding test and set lock

struct spinlock {
    std::atomic_flag f_;

    void lock() {
        while (f_.test_and_set()) {
            sched_yield();
        }
    }
    void unlock() {
        f_.clear();
    }
};

Fairness

2485624
2519544
2486734
2438033

Fairness

2101989 (3156)
2129185 (4436)
2139257 (4579)
2108552 (5182)