Многопоточка

среда, мая 21, 2025 | 3 минуты чтения

Многопоточка

Закон мура: число транзисторов на микрочипах удваивается каждые 2 года.

это значит, что одна программа начинала работать в ~2 раза быстрее (ну вообще нет… но ладно)

в какой-то момент уперлись в физический барьер и уменьшать размер транзисторов сложно

придумали, а давайте будем не увеличивать производительность 1 ядра, а делать процессоры многоядерными

т.е. появилась физическая возможность производить несколько вычислений в 1 такт => то как мы писали программы ранее не подходит, так как они однопоточные

однопоточка:

многопоточка но на самом деле в более сложных программках (лаба про расписания be like)

Concurrency vs Parallelism

Parallelism - физическое выполнение нескольких действий одновременно Concurrency - выполнение двух или более задач одновременно

Мы будем трогать Concurrency, так как мы не будем сильно зацикливаться над количеством ядер. Нам нужно только научится запускать независимые потоки выполнения

С чего начнём осваивать? Конечно же с Hello World на многопоточке!!! Юхуууу

#include <thread>
#include <iostream>

int main(int argc, char** argv) {
	std::thread tr([](){std::cout << "Hello World" << std::endl;});
	tr.join();
return 0;
}

std::thread

прикольная библиотека для многопоточки …

Processes vs threads

раньше: каждая программа - отдельный процесс-поток выполнения (процессы не могут трогать память друг друга)

сейчас программа может запускать несколько потоков внутри процесса (и потоки имеют единую память)

  • Каждый процесс содержит хотя бы один поток
  • Потоки шарят между собой общие ресурсы процесс (памят, файловые дескрипторы и тд)
  • У потоков общее виртуальное адресное пространство
#include <iostream>  
#include <thread>  
  
int main(int argc, char *argv[]) {  
    for (int i = 0; i < 4; ++i) {  
        std::thread tr{  
            []() {  
                int i = 0;  
                std::cout << &i << "\n";  
            }  
        };  
        tr.detach();  
    }  
  
    std:getchar();  
}

вывод:

0x16d28af34
0x16d3a2f34
0x16d316f34
0x16d1fef34

sequintal vs parallel

заполняем 1 миллиард элементов в векторе с помощью рандома sequintal - 20 секунд parallel - 14 секунд

вынесли аллокацию из двух вараций (она была и в sequintal и в parallel, а теперь только в main и пользуемся одним values для того и другого ) sequintal - 8 секунд parallel - 2 секунд

Закон Амдала

много алгоритмов не параллелятся:

  • бабл сорт

Проблемы многопоточки

Race Condition

Ошибка проектирования многопоточной системы или приложения, при которой работа системы или приложения зависит от того, в каком порядке выполняются части кода.

Основная проблема - гонка за временем 4 потока делают result += data[i]

т.е. поток берёт result в один регистр, data[i] в другой регистр и кладёт результат в result в это время тоже самое делают другие потоки

получается один записывает результат, другой результат, а что теряется? а теряется то их сумма

выход? - делать локальные резалты для каждого потока, а потом сумму резалтов используя мьютекс – заблокировали переменную одним потоком, все остальные ждут когда разблокируем, складываем, открываем и теперь тоже самое делает другой поток

как еще решать?

  • mutex (уже было, да)
    • позволяет защитить часть данных от одновременного обращение из разных потоков
  • condition variables
  • semaphores
  • atomic
    • низкоуровневые инструкции процессор
    • хорошо подходит для простых операций (add, store,exchange)
    • не подходит для сложных синхронизаций
    • имеет полные и частичные специализации

DeadLock

  • Ситуация в многозадачной среде, при которой несколько процессов находятся в состояние бесконечного ожидания ресурсов, занятых самими этими процессами

LiveLock

  • Ситуация в которой система не «застревает» (как в обычной взаимной блокировке), а занимается бесполезной работой, её состояние постоянно меняется — но, тем не менее, она «зациклилась», не производит никакой полезной работы

Thread Pool

это механизм, который позволяет эффективно управлять и переиспользовать потоки выполнения. Он предоставляет ограниченное количество заранее созданных потоков, которые могут выполнять задачи из пула

про это не конспектил, но в презенташки кодик вроде понятный, артёмка моисеенко пообещал что не будет такого…