/
Concurrent Tries with Efficient Non-blocking Snapshots Concurrent Tries with Efficient Non-blocking Snapshots

Concurrent Tries with Efficient Non-blocking Snapshots - PowerPoint Presentation

lindy-dunigan
lindy-dunigan . @lindy-dunigan
Follow
377 views
Uploaded On 2018-03-18

Concurrent Tries with Efficient Non-blocking Snapshots - PPT Presentation

Aleksandar Prokopec Phil Bagwell Martin Odersky École Polytechnique Fédérale de Lausanne Nathan Bronson Stanford Motivation val numbers getNumbers compute square roots numbers ID: 656218

snapshot size root ctrie size snapshot ctrie root insert cas immutability hamt actual hash generation mapped array prev remove

Share:

Link:

Embed:

Download Presentation from below link

Download Presentation The PPT/PDF document "Concurrent Tries with Efficient Non-bloc..." is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.


Presentation Transcript

Slide1

Concurrent Tries with Efficient Non-blocking Snapshots

Aleksandar ProkopecPhil BagwellMartin OderskyÉcole Polytechnique Fédérale de Lausanne

Nathan Bronson

StanfordSlide2

Motivation

val numbers = getNumbers()// compute square rootsnumbers foreach

{ entry => x = entry.root

n = entry.number entry.root = 0.5 * (x + n / x) if (abs(entry.root - x) < eps) numbers.remove(entry)}Slide3

Hash Array Mapped Tries (HAMT)Slide4

Hash Array Mapped Tries (HAMT)

0 =

00

00002Slide5

Hash Array Mapped Tries (HAMT)

0Slide6

Hash Array Mapped Tries (HAMT)

0

16 =

0100002Slide7

Hash Array Mapped Tries (HAMT)

016Slide8

Hash Array Mapped Tries (HAMT)

016

4 =

0001002Slide9

Hash Array Mapped Tries (HAMT)

16

0

4 = 00

01

00

2Slide10

Hash Array Mapped Tries (HAMT)

16

0

4Slide11

Hash Array Mapped Tries (HAMT)

16

0

4

12 =

00

1100

2Slide12

Hash Array Mapped Tries (HAMT)

16

0

4

12 = 00

11

00

2Slide13

Hash Array Mapped Tries (HAMT)

16

0

412Slide14

Hash Array Mapped Tries (HAMT)

16

33

0412Slide15

Hash Array Mapped Tries (HAMT)

16

33

0412

48Slide16

Hash Array Mapped Tries (HAMT)

16

0

412

48

33

37Slide17

Hash Array Mapped Tries (HAMT)

16

4

12

48

33

37

0

3Slide18

Hash Array Mapped Tries (HAMT)

4

12

16

20

25

33

37

0

1

8

9

3

48

57Slide19

Immutable HAMT

used as immutable maps in functional languages

4

1216

20

25

33

37

0

1

8

9

3Slide20

Immutable HAMT

updates rewrite path from root to leaf

4

1216

20

25

33

37

0

1

8

9

3

4

12

8

9

11

insert(11)Slide21

Immutable HAMT

updates rewrite path from root to leaf

4

1216

20

25

33

37

0

1

8

9

3

4

12

8

9

11

insert(11)

efficient updates -

log

k

(n)Slide22

Node compression

48

57

4857

1

0

1

0

48

57

1

0

1

0

48

57

10

BITPOP(((1 << ((hc >> lev) & 1F)) – 1) & BMP)Slide23

Node compression

48

57

4857

1

0

1

0

48

57

1

0

1

0

48

57

10

48

57Slide24

Ctrie

Can mutable HAMT be modified to bethread-safe?Slide25

Ctrie insert

4

9

1216

20

25

33

37

0

1

3

48

57

17 = 01

00

01

2Slide26

Ctrie insert

4

9

1216

20

25

33

37

0

1

3

48

57

17 = 0100

01

2

16

17

1) allocateSlide27

Ctrie insert

4

9

12

20

25

33

37

0

1

3

48

57

17 = 010001

2

16

17

2) CASSlide28

Ctrie insert

4

9

12

20

25

33

37

0

1

3

48

57

17 = 010001

2

16

17Slide29

Ctrie insert

4

9

1233

37

0

1

3

48

57

18 = 0100

10

2

16

17

20

25Slide30

Ctrie insert

4

9

1233

37

0

1

3

48

57

18 = 0100

10

2

16

17

20

25

1) allocate

16

17

18Slide31

Ctrie insert

4

9

1233

37

0

1

3

48

57

18 = 010010

2

20

25

2) CAS

16

17

18Slide32

Ctrie insert

4

9

1233

37

0

1

3

48

57

18 = 010010

2

20

25

2) CAS

16

17

18

Unless…Slide33

Ctrie insert

4

9

1233

37

0

1

3

48

57

18 = 0100

10

2

16

17

20

25

T1-1) allocate

16

17

18

Unless…

28 = 01

11

00

2

T1

T2Slide34

Ctrie insert

4

9

120

1

3

18 = 0100

10

2

16

17

20

25

T1-1) allocate

16

17

18

Unless…

28 = 01

11

00

2

T1

T2

20

25

28

T2-1) allocateSlide35

Ctrie insert

4

9

120

1

3

18 = 0100

10

2

16

17

20

25

T1-1) allocate

16

17

18

28 = 01

11

00

2

T1

T2

20

25

28

T2-2) CASSlide36

Ctrie insert

4

9

120

1

3

18 = 0100

10

2

16

17

20

25

T1-2) CAS

16

17

18

28 = 01

11

00

2

T1

T2

20

25

28

T2-2) CASSlide37

Ctrie insert

4

9

120

1

3

18 = 0100

10

2

16

17

20

25

16

17

18

28 = 01

11

00

2

T1

T2

20

25

28

Lost insert!Slide38

Ctrie insert –

2nd attempt

4

9120

1

3

16

17

20

25

Solution: I-nodesSlide39

Ctrie insert –

2nd attempt

4

9120

1

3

16

17

20

25

18 = 0100

10

2

28 = 01

11

00

2

T1

T2Slide40

Ctrie insert –

2nd attempt

4

9120

1

3

16

17

T1

T2

20

25

18 = 0100

10

2

28 = 01

11

00

2

16

17

18

20

25

28

T2-1) allocate

T1-1) allocateSlide41

Ctrie insert –

2nd attempt

4

9120

1

3

16

17

T1

T2

20

25

16

17

18

20

25

28

T2-2) CAS

T1-2) CASSlide42

Ctrie insert –

2nd attempt

4

9120

1

3

16

17

18

20

25

28Slide43

Ctrie insert –

2nd attempt

4

9120

1

3

16

17

18

20

25

28

Idea: once added to the

Ctrie

, I-nodes remain present.Slide44

Ctrie insert –

2nd attempt

4

9120

1

3

16

17

18

20

25

28

Remove operation supported as well - details in the paper.Slide45

Ctrie size

4

9

1201

3

16

17

18

20

25

28Slide46

Ctrie size

4

9

1201

3

16

17

18

20

25

28

size = 0Slide47

Ctrie size

4

9

1201

3

16

17

18

20

25

28

size = 0Slide48

Ctrie size

4

9

1201

3

16

17

18

20

25

28

size = 0Slide49

Ctrie size

4

9

1201

3

16

17

18

20

25

28

size = 0Slide50

Ctrie size

4

9

1201

3

16

17

18

20

25

28

size = 1Slide51

Ctrie size

4

9

1201

3

16

17

18

20

25

28

size = 2Slide52

Ctrie size

4

9

1201

3

16

17

18

20

25

28

size = 3Slide53

Ctrie size

4

9

1201

3

16

17

18

20

25

28

size = 5Slide54

Ctrie size

4

9

1201

3

16

17

18

20

25

28

size = 5

actual size = 12Slide55

Ctrie size

4

9

1201

3

16

17

18

20

25

28

size = 5

0

1

actual size = 12Slide56

Ctrie size

4

9

1201

3

16

17

18

20

25

28

size = 5

0

1

CAS

actual size = 11Slide57

Ctrie size

4

9

12

16

17

18

20

25

28

size = 5

0

1

actual size = 11Slide58

Ctrie size

4

9

12

16

17

18

20

25

28

size = 6

0

1

actual size = 11Slide59

Ctrie size

4

9

12

16

17

18

20

25

28

size

= 6

0

1

actual size = 11

19Slide60

Ctrie size

4

9

12

16

17

18

20

25

28

size

= 6

0

1

actual size = 11

16

17

18

19Slide61

Ctrie size

4

9

12

16

17

18

20

25

28

size

= 6

0

1

actual size = 12

16

17

18

19

CASSlide62

Ctrie size

4

9

12

20

25

28

size

= 6

0

1

actual size = 12

16

17

18

19Slide63

Ctrie size

4

9

12

20

25

28

size

= 6

0

1

actual size = 12

16

17

18

19Slide64

Ctrie size

4

9

12

20

25

28

size = 7

0

1

actual size = 9

16

17

18

19Slide65

Ctrie size

4

9

12

20

25

28

size = 8

0

1

actual size = 12

16

17

18

19Slide66

Ctrie size

4

9

12

20

25

28

size = 9

0

1

actual size = 12

16

17

18

19Slide67

Ctrie size

4

9

12

20

25

28

size = 10

0

1

actual size = 12

16

17

18

19Slide68

Ctrie size

4

9

12

20

25

28

size = 11

0

1

actual size = 12

16

17

18

19Slide69

Ctrie size

4

9

12

20

25

28

size = 12

0

1

actual size = 12

16

17

18

19Slide70

Ctrie size

4

9

12

20

25

28

size = 13

0

1

actual size = 12

16

17

18

19Slide71

Ctrie size

4

9

12

20

25

28

size = 13

0

1

actual size = 12

16

17

18

19

But the size

was never 13!Slide72

Global state information

4

9

12

20

25

28

0

1

16

17

18

19

size

find

filter

iteratorSlide73

Global state information

4

9

12

20

25

28

0

1

16

17

18

19

size

find

filter

iterator

snapshotSlide74

Snapshot using locks

4

9

12

20

25

28

0

1

16

17

18

19Slide75

Snapshot using locks

4

9

12

20

25

28

0

1

16

17

18

19

copy expensiveSlide76

Snapshot using locks

4

9

12

20

25

28

0

1

16

17

18

19

copy expensive

not lock-freeSlide77

Snapshot using locks

4

9

12

20

25

28

0

1

16

17

18

19

copy expensive

not lock-free

can insert or remove remain lock-free?

0

1

2

CASSlide78

Snapshot using locks

4

9

12

20

25

28

0

1

16

17

18

19

copy expensive

not lock-free

can insert or remove remain lock-free?

0

1

2

CASSlide79

Snapshot using logs

4

9

12

20

25

28

0

1

16

17

18

19

keep a linked list of previous values in each I-nodeSlide80

Snapshot using logs

4

9

12

20

25

28

0

1

16

17

18

19

0

1

2

keep a linked list of previous values in each I-nodeSlide81

Snapshot using logs

4

9

12

20

25

28

0

1

16

17

18

19

keep a linked list of previous values in each I-node

when is it safe to delete old entries?

0

1

2Slide82

Snapshot using immutability

4

9

12

20

25

28

0

1

16

17

18

19

rootSlide83

Snapshot using immutability

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

rootSlide84

Snapshot using immutability

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

snapshot!

rootSlide85

Snapshot using immutability

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

snapshot!

#2

root

1) create new I-node at #2Slide86

Snapshot using immutability

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

snapshot!

#2

root

2) set snapshot

snapshot #1Slide87

Snapshot using immutability

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

snapshot!

#2

root

3) CAS root to new I-node

snapshot #1Slide88

Snapshot using immutability

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

subsequent insert

#2

root

snapshot #1

2Slide89

Snapshot using immutability

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

subsequent insert

#2

root

snapshot #1

2

generation #2 - ok!Slide90

Snapshot using immutability

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

subsequent insert

#2

root

snapshot #1

2

generation #1

not ok, too old!Slide91

Snapshot using immutability

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

subsequent insert

#2

root

1) create updated node at #2

snapshot #1

2

#2

#2Slide92

Snapshot using immutability

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

subsequent insert

#2

root

2) CAS to the updated node

snapshot #1

2

#2

#2Slide93

Snapshot using immutability

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

subsequent insert

#2

root

snapshot #1

2

#2

#2

#1 too old!Slide94

Snapshot using immutability

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

subsequent insert

#2

root

snapshot #1

2

#2

#2

4

9

12

#2

1) create updated node at #2Slide95

Snapshot using immutability

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

subsequent insert

#2

root

snapshot #1

2

#2

#2

4

9

12

#2

2) CASSlide96

Snapshot using immutability

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

subsequent insert

#2

root

snapshot #1

#2

#2

4

9

12

#2

0

1

2

finally, create a new leaf

and CASSlide97

Snapshot using immutability

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

another insert

#2

root

snapshot #1

#2

#2

4

9

12

#2

0

1

2

3Slide98

Snapshot using immutability

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

another insert

#2

root

snapshot #1

#2

#2

4

9

12

#2

0

1

2

0

1

2

3Slide99

Snapshot using immutability

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

But... this won't really work... why?

#2

root

snapshot #1

#2

#2

4

9

12

#2

0

1

2

0

1

2

3Slide100

Snapshot using immutability

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

#2

root

snapshot #1

#2

#2

4

9

12

#2

0

1

2

0

1

2

3

T2: remove 19

16

17

18Slide101

Snapshot using immutability

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

#2

root

snapshot #1

#2

#2

4

9

12

#2

0

1

2

0

1

2

3

T2: remove 19

16

17

18

CASSlide102

Snapshot using immutability

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

#2

root

snapshot #1

#2

#2

4

9

12

#2

0

1

2

0

1

2

3

T2: remove 19

16

17

18

CAS

How to fail this last CAS? Slide103

Snapshot using immutability

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

#2

root

snapshot #1

#2

#2

4

9

12

#2

0

1

2

0

1

2

3

T2: remove 19

16

17

18

DCAS

How to fail this last CAS?

DCAS Slide104

Snapshot using immutability

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

#2

root

snapshot #1

#2

#2

4

9

12

#2

0

1

2

0

1

2

3

T2: remove 19

16

17

18

How to fail this last CAS?

DCAS - software based

DCASSlide105

Snapshot using immutability

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

#2

root

snapshot #1

#2

#2

4

9

12

#2

0

1

2

0

1

2

3

T2: remove 19

16

17

18

How to fail this last CAS?

DCAS - software based

...creates intermediate objects

DCASSlide106

GCAS - generation-compare-and-swap

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

#2

root

snapshot #1

#2

#2

4

9

12

#2

0

1

2

3

T2: remove 19

16

17

18

prev

1) set

prev

fieldSlide107

GCAS - generation-compare-and-swap

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

#2

root

snapshot #1

#2

#2

4

9

12

#2

0

1

2

3

T2: remove 19

16

17

18

prev

2) CASSlide108

GCAS - generation-compare-and-swap

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

#2

root

snapshot #1

#2

#2

4

9

12

#2

0

1

2

3

T2: remove 19

16

17

18

prev

3) read root generationSlide109

GCAS - generation-compare-and-swap

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

#2

root

snapshot #1

#2

#2

4

9

12

#2

0

1

2

3

16

17

18

prev

4) if root generation

changed

CAS

prev

to

FailedNode

(

prev

)

FNSlide110

GCAS - generation-compare-and-swap

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

#2

root

snapshot #1

#2

#2

4

9

12

#2

0

1

2

3

16

17

18

prev

4) if root generation

changed

CAS

prev

to

FailedNode

(

prev

)

FNSlide111

GCAS - generation-compare-and-swap

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

#2

root

snapshot #1

#2

#2

4

9

12

#2

0

1

2

3

16

17

18

prev

5) CAS to previous value

FNSlide112

GCAS - generation-compare-and-swap

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

#2

root

snapshot #1

#2

#2

4

9

12

#2

0

1

2

3

16

17

18

prev

4) if root generation

unchanged

CAS

prev

to nullSlide113

GCAS - generation-compare-and-swap

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

#2

root

snapshot #1

#2

#2

4

9

12

#2

0

1

2

3

16

17

18

4) if root generation

unchanged

CAS

prev

to nullSlide114

GCAS - generation-compare-and-swap

4

9

12

20

25

28

0

1

16

17

18

19

#1

#1

#1

#1

#1

#2

root

snapshot #1

#2

#2

4

9

12

#2

0

1

2

3

1) Replace all CAS with GCAS

2) Replace all READ with GCAS_READ

(which checks if

prev

field is null)Slide115

Snapshot-based iterator

def iterator = if (

isSnapshot) new Iterator(root) else snapshot().iterator()Slide116

Snapshot-based size

def size = { val

sz = 0 val it = iterator

while (it.hasNext) sz += 1 sz}Slide117

Snapshot-based size

def size = { val

sz = 0 val it = iterator

while (it.hasNext) sz += 1 sz}Above is O(n).But, by caching size in nodes - amortized O(logkn)!(see source code)Slide118

Snapshot-based atomic clear

def clear() = { val

or = READ(root) val nr = new

INode(new Gen) if (!CAS(root, or, nr)) clear()}(roughly)Slide119

Evaluation - quad core i7Slide120

Evaluation – UltraSPARC T2Slide121

Evaluation – 4x 8-core i7Slide122

Evaluation – snapshotSlide123

Conclusion

snapshots

are

linearizable and lock-freesnapshots take constant timesnapshots are horizontally scalablesnapshots add a non-significant overhead to the algorithm if they aren't usedthe approach may be applicable to tree-based lock-free data-structures in general (intuition)Slide124

Thank you!