Presentation is loading. Please wait.

Presentation is loading. Please wait.

Concurrent Tries with Efficient Non-blocking Snapshots Aleksandar Prokopec Phil Bagwell Martin Odersky École Polytechnique Fédérale de Lausanne Nathan.

Similar presentations


Presentation on theme: "Concurrent Tries with Efficient Non-blocking Snapshots Aleksandar Prokopec Phil Bagwell Martin Odersky École Polytechnique Fédérale de Lausanne Nathan."— Presentation transcript:

1 Concurrent Tries with Efficient Non-blocking Snapshots Aleksandar Prokopec Phil Bagwell Martin Odersky École Polytechnique Fédérale de Lausanne Nathan Bronson Stanford

2 Motivation val numbers = getNumbers() // compute square roots numbers foreach { entry => x = entry.root n = entry.number entry.root = 0.5 * (x + n / x) if (abs(entry.root - x) < eps) numbers.remove(entry) }

3 Hash Array Mapped Tries (HAMT)

4 0 = 000000 2

5 Hash Array Mapped Tries (HAMT) 0

6 0 16 = 010000 2

7 Hash Array Mapped Tries (HAMT) 016

8 Hash Array Mapped Tries (HAMT) 016 4 = 000100 2

9 Hash Array Mapped Tries (HAMT) 16 0 4 = 000100 2

10 Hash Array Mapped Tries (HAMT) 16 04

11 Hash Array Mapped Tries (HAMT) 16 04 12 = 001100 2

12 Hash Array Mapped Tries (HAMT) 16 04 12 = 001100 2

13 Hash Array Mapped Tries (HAMT) 16 0412

14 Hash Array Mapped Tries (HAMT) 1633 0412

15 Hash Array Mapped Tries (HAMT) 1633 0412 48

16 Hash Array Mapped Tries (HAMT) 16 0412 48 3337

17 Hash Array Mapped Tries (HAMT) 16 412 48 3337 03

18 Hash Array Mapped Tries (HAMT) 4121620253337 01893 4857

19 Immutable HAMT used as immutable maps in functional languages 4121620253337 01893

20 Immutable HAMT updates rewrite path from root to leaf 4121620253337 01893 412 8911 insert(11)

21 Immutable HAMT updates rewrite path from root to leaf 4121620253337 01893 412 8911 insert(11) efficient updates - log k (n)

22 Node compression 4857 48571010 48571010 485710 BITPOP(((1 > lev) & 1F)) – 1) & BMP)

23 Node compression 4857 48571010 48571010 485710 4857

24 Ctrie Can mutable HAMT be modified to be thread-safe?

25 Ctrie insert 49121620253337 013 4857 17 = 010001 2

26 Ctrie insert 49121620253337 013 4857 17 = 010001 2 1617 1) allocate

27 Ctrie insert 491220253337 013 4857 17 = 010001 2 1617 2) CAS

28 Ctrie insert 491220253337 013 4857 17 = 010001 2 1617

29 Ctrie insert 49123337 013 4857 18 = 010010 2 1617 2025

30 Ctrie insert 49123337 013 4857 18 = 010010 2 1617 2025 1) allocate 161718

31 Ctrie insert 49123337 013 4857 18 = 010010 2 2025 2) CAS 161718

32 Ctrie insert 49123337 013 4857 18 = 010010 2 2025 2) CAS 161718 Unless…

33 Ctrie insert 49123337 013 4857 18 = 010010 2 1617 2025 T1-1) allocate 161718 Unless… 28 = 011100 2 T1 T2

34 Ctrie insert 4912 013 18 = 010010 2 1617 2025 T1-1) allocate 161718 Unless… 28 = 011100 2 T1 T2 202528 T2-1) allocate

35 Ctrie insert 4912 013 18 = 010010 2 1617 2025 T1-1) allocate 161718 28 = 011100 2 T1 T2 202528 T2-2) CAS

36 Ctrie insert 4912 013 18 = 010010 2 1617 2025 T1-2) CAS 161718 28 = 011100 2 T1 T2 202528 T2-2) CAS

37 Ctrie insert 4912 013 18 = 010010 2 1617 2025 161718 28 = 011100 2 T1 T2 202528 Lost insert!

38 Ctrie insert – 2 nd attempt 4912 0131617 2025 Solution: I-nodes

39 Ctrie insert – 2 nd attempt 4912 0131617 2025 18 = 010010 2 28 = 011100 2 T1 T2

40 Ctrie insert – 2 nd attempt 4912 0131617 T1 T2 2025 18 = 010010 2 28 = 011100 2 161718 202528 T2-1) allocate T1-1) allocate

41 Ctrie insert – 2 nd attempt 4912 0131617 T1 T2 2025 161718 202528 T2-2) CAS T1-2) CAS

42 Ctrie insert – 2 nd attempt 4912 013161718 202528

43 Ctrie insert – 2 nd attempt 4912 013161718 202528 Idea: once added to the Ctrie, I-nodes remain present.

44 Ctrie insert – 2 nd attempt 4912 013161718 202528 Remove operation supported as well - details in the paper.

45 Ctrie size 4912 013161718 202528

46 Ctrie size 4912 013161718 202528 size = 0

47 Ctrie size 4912 013161718 202528 size = 0

48 Ctrie size 4912 013161718 202528 size = 0

49 Ctrie size 4912 013161718 202528 size = 0

50 Ctrie size 4912 013161718 202528 size = 1

51 Ctrie size 4912 013161718 202528 size = 2

52 Ctrie size 4912 013161718 202528 size = 3

53 Ctrie size 4912 013161718 202528 size = 5

54 Ctrie size 4912 013161718 202528 size = 5 actual size = 12

55 Ctrie size 4912 013161718 202528 size = 5 01 actual size = 12

56 Ctrie size 4912 013161718 202528 size = 5 01 CAS actual size = 11

57 Ctrie size 4912 161718 202528 size = 5 01 actual size = 11

58 Ctrie size 4912 161718 202528 size = 6 01 actual size = 11

59 Ctrie size 4912 161718 202528 size = 6 01 actual size = 11 19

60 Ctrie size 4912 161718 202528 size = 6 01 actual size = 11 161718 19

61 Ctrie size 4912 161718 202528 size = 6 01 actual size = 12 161718 19 CAS

62 Ctrie size 4912202528 size = 6 01 actual size = 12 161718 19

63 Ctrie size 4912202528 size = 6 01 actual size = 12 161718 19

64 Ctrie size 4912202528 size = 7 01 actual size = 9 161718 19

65 Ctrie size 4912202528 size = 8 01 actual size = 12 161718 19

66 Ctrie size 4912202528 size = 9 01 actual size = 12 161718 19

67 Ctrie size 4912202528 size = 10 01 actual size = 12 161718 19

68 Ctrie size 4912202528 size = 11 01 actual size = 12 161718 19

69 Ctrie size 4912202528 size = 12 01 actual size = 12 161718 19

70 Ctrie size 4912202528 size = 13 01 actual size = 12 161718 19

71 Ctrie size 4912202528 size = 13 01 actual size = 12 161718 19 But the size was never 13!

72 Global state information 4912202528 01 161718 19 size find filter iterator

73 Global state information 4912202528 01 161718 19 size find filter iterator  snapshot

74 Snapshot using locks 4912202528 01 161718 19

75 Snapshot using locks 4912202528 01 161718 19 copy expensive

76 Snapshot using locks 4912202528 01 161718 19 copy expensive not lock-free

77 Snapshot using locks 4912202528 01 161718 19 copy expensive not lock-free can insert or remove remain lock-free? 01 2 CAS

78 Snapshot using locks 4912202528 01 161718 19 copy expensive not lock-free can insert or remove remain lock-free? 01 2 CAS

79 Snapshot using logs 4912202528 01 161718 19 keep a linked list of previous values in each I-node

80 Snapshot using logs 4912202528 01 161718 19 01 2 keep a linked list of previous values in each I-node

81 Snapshot using logs 4912202528 01 161718 19 keep a linked list of previous values in each I-node when is it safe to delete old entries? 01 2

82 Snapshot using immutability 4912202528 01 161718 19 root

83 Snapshot using immutability 4912202528 01 161718 19 #1 root

84 Snapshot using immutability 4912202528 01 161718 19 #1 snapshot! root

85 Snapshot using immutability 4912202528 01 161718 19 #1 snapshot! #2 root 1) create new I-node at #2

86 Snapshot using immutability 4912202528 01 161718 19 #1 snapshot! #2 root 2) set snapshot snapshot #1

87 Snapshot using immutability 4912202528 01 161718 19 #1 snapshot! #2 root 3) CAS root to new I-node snapshot #1

88 Snapshot using immutability 4912202528 01 161718 19 #1 subsequent insert #2 rootsnapshot #1 2

89 Snapshot using immutability 4912202528 01 161718 19 #1 subsequent insert #2 rootsnapshot #1 2 generation #2 - ok!

90 Snapshot using immutability 4912202528 01 161718 19 #1 subsequent insert #2 rootsnapshot #1 2 generation #1 not ok, too old!

91 Snapshot using immutability 4912202528 01 161718 19 #1 subsequent insert #2 root 1) create updated node at #2 snapshot #1 2 #2

92 Snapshot using immutability 4912202528 01 161718 19 #1 subsequent insert #2 root 2) CAS to the updated node snapshot #1 2 #2

93 Snapshot using immutability 4912202528 01 161718 19 #1 subsequent insert #2 rootsnapshot #1 2 #2 #1 too old!

94 Snapshot using immutability 4912202528 01 161718 19 #1 subsequent insert #2 rootsnapshot #1 2 #2 4912 #2 1) create updated node at #2

95 Snapshot using immutability 4912202528 01 161718 19 #1 subsequent insert #2 rootsnapshot #1 2 #2 4912 #2 2) CAS

96 Snapshot using immutability 4912202528 01 161718 19 #1 subsequent insert #2 rootsnapshot #1 #2 4912 #2 01 2 finally, create a new leaf and CAS

97 Snapshot using immutability 4912202528 01 161718 19 #1 another insert #2 rootsnapshot #1 #2 4912 #2 01 2 3

98 Snapshot using immutability 4912202528 01 161718 19 #1 another insert #2 rootsnapshot #1 #2 4912 #2 01 2 01 23

99 Snapshot using immutability 4912202528 01 161718 19 #1 But... this won't really work... why? #2 rootsnapshot #1 #2 4912 #2 01 2 01 23

100 Snapshot using immutability 4912202528 01 161718 19 #1 #2 rootsnapshot #1 #2 4912 #2 01 2 01 23 T2: remove 19 161718

101 Snapshot using immutability 4912202528 01 161718 19 #1 #2 rootsnapshot #1 #2 4912 #2 01 2 01 23 T2: remove 19 161718 CAS

102 Snapshot using immutability 4912202528 01 161718 19 #1 #2 rootsnapshot #1 #2 4912 #2 01 2 01 23 T2: remove 19 161718 CAS How to fail this last CAS?

103 Snapshot using immutability 4912202528 01 161718 19 #1 #2 rootsnapshot #1 #2 4912 #2 01 2 01 23 T2: remove 19 161718 DCAS How to fail this last CAS? DCAS

104 Snapshot using immutability 4912202528 01 161718 19 #1 #2 rootsnapshot #1 #2 4912 #2 01 2 01 23 T2: remove 19 161718 How to fail this last CAS? DCAS - software based DCAS

105 Snapshot using immutability 4912202528 01 161718 19 #1 #2 rootsnapshot #1 #2 4912 #2 01 2 01 23 T2: remove 19 161718 How to fail this last CAS? DCAS - software based...creates intermediate objects DCAS

106 GCAS - generation-compare-and-swap 4912202528 01 161718 19 #1 #2 rootsnapshot #1 #2 4912 #2 01 23 T2: remove 19 161718 prev 1) set prev field

107 GCAS - generation-compare-and-swap 4912202528 01 161718 19 #1 #2 rootsnapshot #1 #2 4912 #2 01 23 T2: remove 19 161718 prev 2) CAS

108 GCAS - generation-compare-and-swap 4912202528 01 161718 19 #1 #2 rootsnapshot #1 #2 4912 #2 01 23 T2: remove 19 161718 prev 3) read root generation

109 GCAS - generation-compare-and-swap 4912202528 01 161718 19 #1 #2 rootsnapshot #1 #2 4912 #2 01 23 161718 prev 4) if root generation changed CAS prev to FailedNode(prev) FN

110 GCAS - generation-compare-and-swap 4912202528 01 161718 19 #1 #2 rootsnapshot #1 #2 4912 #2 01 23 161718 prev 4) if root generation changed CAS prev to FailedNode(prev) FN

111 GCAS - generation-compare-and-swap 4912202528 01 161718 19 #1 #2 rootsnapshot #1 #2 4912 #2 01 23 161718 prev 5) CAS to previous value FN

112 GCAS - generation-compare-and-swap 4912202528 01 161718 19 #1 #2 rootsnapshot #1 #2 4912 #2 01 23 161718 prev 4) if root generation unchanged CAS prev to null

113 GCAS - generation-compare-and-swap 4912202528 01 161718 19 #1 #2 rootsnapshot #1 #2 4912 #2 01 23 161718 4) if root generation unchanged CAS prev to null

114 GCAS - generation-compare-and-swap 4912202528 01 161718 19 #1 #2 rootsnapshot #1 #2 4912 #2 01 23 1) Replace all CAS with GCAS 2) Replace all READ with GCAS_READ (which checks if prev field is null)

115 Snapshot-based iterator def iterator = if (isSnapshot) new Iterator(root) else snapshot().iterator()

116 Snapshot-based size def size = { val sz = 0 val it = iterator while (it.hasNext) sz += 1 sz }

117 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(log k n)! (see source code)

118 Snapshot-based atomic clear def clear() = { val or = READ(root) val nr = new INode(new Gen) if (!CAS(root, or, nr)) clear() } (roughly)

119 Evaluation - quad core i7

120 Evaluation – UltraSPARC T2

121 Evaluation – 4x 8-core i7

122 Evaluation – snapshot

123 Conclusion snapshots are linearizable and lock-free snapshots take constant time snapshots are horizontally scalable snapshots add a non-significant overhead to the algorithm if they aren't used the approach may be applicable to tree-based lock-free data-structures in general (intuition)

124 Thank you!


Download ppt "Concurrent Tries with Efficient Non-blocking Snapshots Aleksandar Prokopec Phil Bagwell Martin Odersky École Polytechnique Fédérale de Lausanne Nathan."

Similar presentations


Ads by Google