cpp-2013 #19 Concurrency

27
Concurrency

Transcript of cpp-2013 #19 Concurrency

Page 1: cpp-2013 #19 Concurrency

Concurrency

Page 2: cpp-2013 #19 Concurrency

Типові приклади використанняResponsiveness

Багатозадачність ОС

Виконання операцій поза UI (I/O)

Performance

Обробка даних паралельно (CPU)

Виконання кількох задач паралельно(CPU-CPU, CPU-I/O, I/O-I/O)

Page 3: cpp-2013 #19 Concurrency

ProcessПроцес визначає virtual address space

Досягається ізоляція, оскільки

- процеси не можуть напряму адресувати пам’ять інших процесів

Також можливе спільне використання:

- спільна бібліотека може входити до адресного простору кількох процесів

Page 4: cpp-2013 #19 Concurrency

Процес не виконує код,

а лише надає ресурси і контекст для виконання потоків

Page 5: cpp-2013 #19 Concurrency

Потоки (threads) виконують код

Потоки виконуються в межах процесу

Мають доступ до всього адресного простору процесу.

Кожен потік має свій стек викликів (локальні змінні), вказівник поточної інструкції та значення регістрів CPU

Page 6: cpp-2013 #19 Concurrency

Виконання потоків у Windows- Багатозадачна ОС

- Витісняюче планування на основі пріоритетів

- (preemptive scheduling, priority-based)

- CPU завжди виконує той потік, який має найвищий пріоритет (і який готовий до виконання)

Page 7: cpp-2013 #19 Concurrency

Планування (scheduling) Windows- Потік виконується протягом фіксованого інтервалу

часу (time slice)

- По закінченню інтервалу ОС перевіряє, чи є готовий потік з таким же пріоритетом

- Якщо є, потік витісняється

- Як тільки з’являється потік з вищим пріоритетом, потік витісняється

- Навіть якщо його інтервал не закінчився

Page 8: cpp-2013 #19 Concurrency

Переключення контексту

(context switching)Вибравши новий потік для виконання, ОС переключає контекст:

Зберігається стан регістрів CPU + IP попереднього потоку

Відновлюються регістри CPU нового потоку

Page 9: cpp-2013 #19 Concurrency

Потік звільняє CPU, коли:- Завершився time slice

- Переходить в стан очікування самостійно

- Диск, мережа, пам’ять (!), синхронізація

- Витісняється потоком з вищим пріоритетом

- Який закінчив щось очікувати (диск, мережа,...)

- Пріоритет якого збільшився

- Потік завершується

- …

Page 10: cpp-2013 #19 Concurrency

Windows та Linux планують потоки, не процеси

Наслідок:

Процес А має 1 потік

Процес Б має 9 потоків

Процес Б отримає 90% процесорного часу

(за умови однакового пріоритету потоків)

Page 11: cpp-2013 #19 Concurrency

UI message loop- Один GUI потік обробляє повідомлення з черги:

- Clicks, repaints, mouse moves, key presses, …

- Події обробляються послідовно

- Отже, якщо одна подія займає довгий час, решта будуть чекати

- Отже, довготривалі події ніколи не повинні виконуватись в UI потоці

- I/O, важкі обчислення (див. наст. слайд)

Page 12: cpp-2013 #19 Concurrency

Довготривалі події ніколине повинні виконуватись в UI потоці- UI потік не повинен блокуватись чекаючи

завершення цих операцій

- В т.ч. коли ці операції виконуються іншим потоком

- Для повернення результатів – signals and slots

- “Qt developers are used to working with this kind of asynchronous behavior”http://qt-project.org/doc/qt-5.0/qtcore/thread-basics.html

Page 13: cpp-2013 #19 Concurrency

Thread pool- Створювати і видаляти потоки дорого

- Пул потоків виконує завдання використовуючи створений наперед набір потоків

- Залежно від навантаження пул створює додаткові потоки або видаляє непотрібні

Page 14: cpp-2013 #19 Concurrency

Типові задачі- Поділити дані на частини і обробляти

паралельно

- Виконувати декілька незалежних задач паралельно

- Виконати довготривалу операцію поза UI

Page 15: cpp-2013 #19 Concurrency

Паралелізм даних

...

Thread 1

...

Thread 2

Page 16: cpp-2013 #19 Concurrency

Паралельні незалежні задачі

Task 1

Task 2

Task 3

SeqSeq

Page 17: cpp-2013 #19 Concurrency

Паралельні незалежні задачі

Seq

Future

Seq Seq

Page 18: cpp-2013 #19 Concurrency

Seq

Future

Seq

Future

Seq

Future

Seq Seq

Паралельні незалежні задачі

Page 19: cpp-2013 #19 Concurrency

Операції поза UI

Seq

DB Call

Event loop

Seq

Page 20: cpp-2013 #19 Concurrency

Використання спільних данихauto count = 0;

100{

{count++;

});}

int temp = count;temp = temp + 1;count = temp;

Page 21: cpp-2013 #19 Concurrency

Використання спільних даних

Потік A

int temp = count; // 0

temp = temp + 1; // 1

count = temp; // 1

count = 0

Потік B

int temp = count; // 0

temp = temp + 1; // 1

count = temp; // 1

count = 1 // WRONG! Should be 2

Page 22: cpp-2013 #19 Concurrency

Доступ до спільних даних повинен бути синхронізованимauto count = 0;std::mutex mutex;

{

{std::lock_guard<std::mutex> lock(mutex);count++;

});}

mutex.lock();// ...mutex.unlock();

Qt has its own bicycle for this

Page 23: cpp-2013 #19 Concurrency

Використання спільних даних

Потік Amutex.lock();int temp = count; // 0

temp = temp + 1; // 1count = temp; // 1mutex.unlock();

count = 0

Потік B

mutex.lock();

int temp = count; // 0temp = temp + 1; // 1count = temp; // 1mutex.unlock();

Page 24: cpp-2013 #19 Concurrency

Синхронізацією керувати складноБагато нюансів, про які ми навіть не здогадуємось (як з count++)Second order ignorance http://c2.com/cgi/wiki?OrdersOfIgnorance

Використовуйте готові засоби: алгоритми, конкурентні колекції, tasks, futures, QtConcurrent, QThreadPool, signals and slots

Page 25: cpp-2013 #19 Concurrency

Advanced Qt

• Thread-safety and reentrance

• Working with threads

• Basic synchronization techniques

• High-level concurrency API

Page 26: cpp-2013 #19 Concurrency

Working with threads

• QThread - a wrapper around OS thread

• do not subclass QThread

• push processing objects to QThread instance

• do not allocate heap memory in processing object constructor

• be sure that thread is shut down when deleting QThread

• be careful while connecting signals/slots in multithreading applications

Page 27: cpp-2013 #19 Concurrency

Basic synchronization techniques

• QMutex and QMutexLocker

• QReadWriteLock