Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.
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.180 Aufrufe

Veröffentlicht am

Lock-free maps

Veröffentlicht in: Software
  • Als Erste(r) kommentieren

Максим Хижинский 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

×