Concurrent mapS
C++ Russia 2015Maxim Khizhinsky
Lock-free hash tableLock-free hash table
LIBCDS
Максим Хижинский, C++ Russia 2015
0 1 2 3 4 5 6
X X X
k1
k
k
k k
k
kk
k
k
...
Lock-free ordered listLock-free ordered list
LIBCDS
Максим Хижинский, C++ Russia 2015
Операции:
●
insert( node )
● erase( ...
CAS — compare-and-swapCAS — compare-and-swap
LIBCDS
Максим Хижинский, C++ Russia 2015
template <typename T>
bool CAS( T * ...
Lock-free list: insertLock-free list: insert
LIBCDS
Максим Хижинский, C++ Russia 2015
H T52 8
3
H T52 8
3
3. prev->next_.C...
Lock-free list: eraseLock-free list: erase
LIBCDS
Максим Хижинский, C++ Russia 2015
1. find key 3
2. prev->next_.CAS( foun...
Lock-free list: insert/eraseLock-free list: insert/erase
LIBCDS
Максим Хижинский, C++ Russia 2015
A: find key 3
H T52 8
pr...
Marked pointerMarked pointer
LIBCDS
Максим Хижинский, C++ Russia 2015
[ T.Harris, 2001 ]
Двухфазное удаление:
● Логическое...
Lock-free list: marked pointerLock-free list: marked pointer
LIBCDS
Максим Хижинский, C++ Russia 2015
H T52 8
prev
3
found...
Lock-free list: problemsLock-free list: problems
LIBCDS
Максим Хижинский, C++ Russia 2015
H T52 8
prev
3
found
iprev inext...
Lock-free list: problemsLock-free list: problems
LIBCDS
Максим Хижинский, C++ Russia 2015
Проблемы:
●
Защита локальных дан...
ABA-проблемаABA-проблема
LIBCDS
Максим Хижинский, C++ Russia 2015
52
prev
3
found next
Thread A: erase(3) Thread B
52 3
er...
SMRSMR
LIBCDS
Максим Хижинский, C++ Russia 2015
Проблемы:
● Защита локальных данных — когда элемент можно
безопасно удалит...
Tagged pointersTagged pointers
LIBCDS
Максим Хижинский, C++ Russia 2015
pointer tag
prev->next_.dwCAS( found, <next.ptr, p...
Tagged pointers: historyTagged pointers: history
LIBCDS
Максим Хижинский, C++ Russia 2015
ABA-проблема характерна только д...
Hazard pointersHazard pointers
LIBCDS
Максим Хижинский, C++ Russia 2015
✔ Использует только атомарные чтение/запись
 Защи...
Hazard pointersHazard pointers
LIBCDS
Максим Хижинский, C++ Russia 2015
H T52 8
prev
3
found next
erase( Key k ) {
hp_guar...
Hazard pointersHazard pointers
LIBCDS
Максим Хижинский, C++ Russia 2015
P – thread count
Thread 0
Thread HP Manager
0
1
…
...
Hazard PointersHazard Pointers
LIBCDS
Максим Хижинский, C++ Russia 2015
Объявление Hazard Pointer'а – защита локальной ссы...
Hazard PointersHazard Pointers
LIBCDS
Максим Хижинский, C++ Russia 2015
Удаление элемента
void hp_retire( T * what ) {
pus...
User-space Read-Copy UpdateUser-space Read-Copy Update
LIBCDS
Максим Хижинский, C++ Russia 2015
✔ RCU — метод синхронизаци...
User-space RCUUser-space RCU
LIBCDS
Максим Хижинский, C++ Russia 2015
Map.find( ... );
Set.insert( ... );
Map.find( ... );...
Lock-free hash tableLock-free hash table
LIBCDS
Максим Хижинский, C++ Russia 2015
0 1 2 3 4 5 6
X X X
k1
k
k
k k
k
kk
k
k
...
Split-ordered listSplit-ordered list
LIBCDS
Максим Хижинский, C++ Russia 2015
0 8 2 1 9 13
T[0]
T[1]
k iSentinel node Regu...
Skip listSkip list
LIBCDS
Максим Хижинский, C++ Russia 2015
X
X
X
X
X
X
X
X10 15 23 34 5542
23
Tower
h = 3
Вероятностная с...
PerformancePerformance
LIBCDS
Максим Хижинский, C++ Russia 2015
Intel Dual Xeon X5670 2.93 GHz 12 cores 24 threads / 24 GB...
Concurrent mapsConcurrent maps
Максим Хижинский, C++ Russia 2015
Спасибо за внимание!
libcds.dev@gmail.com
https://github....
Nächste SlideShare
Wird geladen in …5
×

Максим Хижинский Lock-free maps

2.144 Aufrufe

Veröffentlicht am

Lock-free maps

Veröffentlicht in: Software
0 Kommentare
1 Gefällt mir
Statistik
Notizen
  • Als Erste(r) kommentieren

Keine Downloads
Aufrufe
Aufrufe insgesamt
2.144
Auf SlideShare
0
Aus Einbettungen
0
Anzahl an Einbettungen
1.384
Aktionen
Geteilt
0
Downloads
9
Kommentare
0
Gefällt mir
1
Einbettungen 0
Keine Einbettungen

Keine Notizen für die Folie

Максим Хижинский Lock-free maps

  1. 1. Concurrent mapS C++ Russia 2015Maxim Khizhinsky
  2. 2. Lock-free hash tableLock-free hash table LIBCDS Максим Хижинский, C++ Russia 2015 0 1 2 3 4 5 6 X X X k1 k k k k k kk k k 2 3 4 5 6 7 8 9 T[8] Lock-free список коллизий 7 k 10
  3. 3. Lock-free ordered listLock-free ordered list LIBCDS Максим Хижинский, C++ Russia 2015 Операции: ● insert( node ) ● erase( key ) ● find( key ) template <class T> struct node { std::atomic<node*> next_; T data_; }; H T52 8 Lock-free примитивы: ● atomic load/store ● atomic compare-and-swap (CAS)
  4. 4. CAS — compare-and-swapCAS — compare-and-swap LIBCDS Максим Хижинский, C++ Russia 2015 template <typename T> bool CAS( T * pAtomic, T expected, T desired ) atomically { if ( *pAtomic == expected ) { *pAtomic = desired; return true; } else return false; };
  5. 5. Lock-free list: insertLock-free list: insert LIBCDS Максим Хижинский, C++ Russia 2015 H T52 8 3 H T52 8 3 3. prev->next_.CAS( next, new_node ) 1. find insert position for key 3 2. new_node.next_.store( next ) H T52 8 prev next new_node
  6. 6. Lock-free list: eraseLock-free list: erase LIBCDS Максим Хижинский, C++ Russia 2015 1. find key 3 2. prev->next_.CAS( found, next ) H T52 8 prev 3 found H T52 83 Проблема: параллельный insert next
  7. 7. Lock-free list: insert/eraseLock-free list: insert/erase LIBCDS Максим Хижинский, C++ Russia 2015 A: find key 3 H T52 8 prev 3 found B: find insert pos for key 4 iprev inext A: erase key 3 H T52 83 prev->next_.CAS( found, next ) next B: insert key 4 H T52 83 4 iprev->next_.CAS( inext, new_item ) local vars
  8. 8. Marked pointerMarked pointer LIBCDS Максим Хижинский, C++ Russia 2015 [ T.Harris, 2001 ] Двухфазное удаление: ● Логическое удаление — помечаем элемент ● Физическое удаление — исключаем элемент В качестве метки используем младший бит указателя
  9. 9. Lock-free list: marked pointerLock-free list: marked pointer LIBCDS Максим Хижинский, C++ Russia 2015 H T52 8 prev 3 found iprev inext nextA: erase B: insert A: Logical deletion - mark item found H T52 83 found->next_.CAS( next, next | 1 ) B: iprev->next_.CAS( inext, new_item ) - failed!!! A: Physical deletion - remove item found H T52 83 prev->next_.CAS( found, next )
  10. 10. Lock-free list: problemsLock-free list: problems LIBCDS Максим Хижинский, C++ Russia 2015 H T52 8 prev 3 found iprev inext nextA: erase B: insert iprev->next_.CAS( inext, new_item ) prev->next_.CAS( found, next ) local vars Вдруг уже удалены?..
  11. 11. Lock-free list: problemsLock-free list: problems LIBCDS Максим Хижинский, C++ Russia 2015 Проблемы: ● Защита локальных данных — когда элемент можно безопасно удалить? ● ABA-проблема
  12. 12. ABA-проблемаABA-проблема LIBCDS Максим Хижинский, C++ Russia 2015 52 prev 3 found next Thread A: erase(3) Thread B 52 3 erase(3); erase(5) 2 3 insert(4) Heap new node(4) alloc delete 42 preempted... 42 prev found next 5 addr(3) == addr(4) prev->next_.CAS( found, next ) - success!!! 2 мусор
  13. 13. SMRSMR LIBCDS Максим Хижинский, C++ Russia 2015 Проблемы: ● Защита локальных данных — когда элемент можно безопасно удалить? ● ABA-проблема Решение: Safe memory reclamation (SMR) ● Tagged pointers ● Hazard Pointers ● User-space RCU
  14. 14. Tagged pointersTagged pointers LIBCDS Максим Хижинский, C++ Russia 2015 pointer tag prev->next_.dwCAS( found, <next.ptr, prev->next_.tag + 1> ) template <class T> struct tagged_ptr { T * ptr; uintptr_t tag; }; Требует dwCAS — не везде есть Решает только ABA-проблему Освободить память нельзя, нужен free-list [ boost.lock-free ] H T52 8 prev 3 found next
  15. 15. Tagged pointers: historyTagged pointers: history LIBCDS Максим Хижинский, C++ Russia 2015 ABA-проблема характерна только для CAS Архитектуры процессоров LL/SC: ● IBM PowerPC ● MIPS ● ARM ➢ LL — load linked ➢ SC — store conditional bool weak_CAS( T * ptr, T expected, T desired ) { T cur = LL( ptr ); return cur == expected && SC( ptr, desired ); } Эмуляция LL/SC на CAS — намного труднее CAS: ● x86, amd64 ● Sparc ● Itanium С++11 — только CAS
  16. 16. Hazard pointersHazard pointers LIBCDS Максим Хижинский, C++ Russia 2015 ✔ Использует только атомарные чтение/запись  Защищает только локальные ссылки ✔ Размер массива отложенных (готовых к удалению) элементов ограничен сверху  Перед работой с указателем его следует объявить как hazard решает ABA-проблему Физическое удаление элементов
  17. 17. Hazard pointersHazard pointers LIBCDS Максим Хижинский, C++ Russia 2015 H T52 8 prev 3 found next erase( Key k ) { hp_guard h1 = get_guard(); hp_guard h2 = get_guard(); retry: node * prev = Head; do { node * found = h2.protect( prev->next_); if ( found->key == k ) if (prev->next_.CAS( found, found->next_)) { hp_retire( found ); return true; } else goto retry; h1 = h2; prev = found; } while ( found->key < k ); return false; } Распределяем HP (TLS) Защищаем элемент Удаляем элемент
  18. 18. Hazard pointersHazard pointers LIBCDS Максим Хижинский, C++ Russia 2015 P – thread count Thread 0 Thread HP Manager 0 1 … K - 1 HP[K] 0 1 2 … R - 1 Retired[R] Hazard Pointer Singleton Thread 1 Thread P - 1 K = 4 R = 2 KP <K,P, R> : R > K * P
  19. 19. Hazard PointersHazard Pointers LIBCDS Максим Хижинский, C++ Russia 2015 Объявление Hazard Pointer'а – защита локальной ссылки class hp_guard { void * hp; // ... }; T * hp_guard::protect( std::atomic<T*>& what) { T * t; do { hp = t = what.load(); } while (t != what.load()); return t; } 0 1 … K - 1 HP[K]
  20. 20. Hazard PointersHazard Pointers LIBCDS Максим Хижинский, C++ Russia 2015 Удаление элемента void hp_retire( T * what ) { push what to current_thread.Retired array if ( current_thread.Retired is full ) hp.Scan( current_thread ); } void hp::Scan() { void * guarded[K*P] = union HP[K] for all P thread; foreach ( p in current_thread.Retired[R] ) if ( p not in guarded[] ) delete p; } <K,P, R> : R > K * P 0 1 2 … R - 1 Retired[R] 0 1 … K - 1 HP[K]
  21. 21. User-space Read-Copy UpdateUser-space Read-Copy Update LIBCDS Максим Хижинский, C++ Russia 2015 ✔ RCU — метод синхронизации: RCU.lock() / RCU.unlock() ✔ Разработан для почти-read-only данных (map, set) ✔ Очень легкие read-side lock ✔ Удаление элемента — ожидание окончания эпохи решает ABA-проблему Физическое удаление элементов RCU.lock(): ничего не блокирует Объявляет, что поток входит в текущую RCU-эпоху
  22. 22. User-space RCUUser-space RCU LIBCDS Максим Хижинский, C++ Russia 2015 Map.find( ... ); Set.insert( ... ); Map.find( ... ); Map.erase( ... )... Thread 1 Set.find( ... ); Map.insert( ... ); Set.find( ... ); Set.insert( ... ); Thread N Эпоха 1 RCU.sync() - ждем, пока все потоки покинут эпоху 1 Set.find( ... ); Map.insert( ... ); Set.find( ... ); Set.insert( ... ); ... Map.erase; Map.find( ... ); Set.insert( ... ); Map.find( ... ); ++Эпоха Эпоха 2
  23. 23. Lock-free hash tableLock-free hash table LIBCDS Максим Хижинский, C++ Russia 2015 0 1 2 3 4 5 6 X X X k1 k k k k k kk k k 2 3 4 5 6 7 8 9 T[8] Lock-free cписок: HP/RCU + marked pointers 7 k 10 Hash table + Lock-free ordered list No rehashing
  24. 24. Split-ordered listSplit-ordered list LIBCDS Максим Хижинский, C++ Russia 2015 0 8 2 1 9 13 T[0] T[1] k iSentinel node Regular node N = 2 size() = 4 Load factor L: size() / N ≤ L Если L = 2, то вставка нового элемента приводит к увеличению hash table Hash table Lock-free ordered list
  25. 25. Skip listSkip list LIBCDS Максим Хижинский, C++ Russia 2015 X X X X X X X X10 15 23 34 5542 23 Tower h = 3 Вероятностная структура данных: P[ h == 1 ] = 1/2 P[ h == k ] = 1/2 k , 0 < k < 32 h = lsb( rand() ) O(log(N))
  26. 26. PerformancePerformance LIBCDS Максим Хижинский, C++ Russia 2015 Intel Dual Xeon X5670 2.93 GHz 12 cores 24 threads / 24 GB RAM
  27. 27. Concurrent mapsConcurrent maps Максим Хижинский, C++ Russia 2015 Спасибо за внимание! libcds.dev@gmail.com https://github.com/khizmax/libcds

×