Корректировка конспектов лекций (#131)

* Корректировки конспектов лекций

* Корректировка конспекта лекции 5

* Корректировка конспекта лекции 8

* Корректировка конспекта лекции 9

* Корректировка конспекта лекции 10

* Корректировка конспекта лекции 11

* Корректировка конспекта лекции 12

* Корректировка конспекта лекции 13

* Корректировка конспекта лекции 12

* Корректировка конспекта лекции 14

* Корректировка конспекта лекции 16

* Корректировка конспекта лекции 17

* Корректировка конспекта лекции

* Корректировка конспекта лекции 20

* Корректировка конспекта лекции 21

* Корректировка конспекта лекции 22

* Корректировка конспекта лекции 23

* Корректировка конспекта лекции 13

* Корректировка конспекта лекции 12

* Корректировка конспекта лекции 20
This commit is contained in:
markast555
2025-06-22 16:54:22 +03:00
committed by GitHub
parent 773af1088c
commit 469f42e7f5
16 changed files with 116 additions and 111 deletions

View File

@@ -54,16 +54,16 @@
### Коммуникационные модели
В коммуникационной моделью с общей памятью есть:
В коммуникационной модели с общей памятью есть:
- есть единое адресное пространство для потоков;
- единое адресное пространство для потоков;
- общение между потоками происходит через неявную связь с помощью загрузки и сохранения в память.
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_01.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_01.jpg)
*Рис. 1. Коммуникационная модель с общей памятью.*
В коммуникационной моделью с обменом сообщениями присутствуют:
В коммуникационной модели с обменом сообщениями присутствуют:
- разделенное адресное пространство (у каждого из процессоров своя память);
- общение между потоками происходит явной связи путем отправки и получения сообщений.
@@ -87,11 +87,11 @@
Рассмотрим ситуацию, когда процесс порождает два параллельных потока `P₁` и `P₂` и впоследствии использует результаты их вычислений. После создания, процесс сможет продолжить дальнейшее выполнение только когда будут выполнены оба потока, а значит есть необходимость их синхронизировать.
- Проиводитель-потребитель (producer-consumer): потребительский процесс должен ждать, пока процесс производителя не произведет данные (то есть потребитель не может продолжать выполнение, пока производитель не произведёт какие-то данные).
- Производитель-потребитель (producer-consumer): потребительский процесс должен ждать, пока процесс производителя не произведет данные (то есть потребитель не может продолжать выполнение, пока производитель не произведёт какие-то данные).
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_04.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_04.jpg)
*Рис. 4. Способ синхронизации параллельных процессов "Проиводитель-потребитель" (producer-consumer).
*Рис. 4. Способ синхронизации параллельных процессов "Проиводитель-потребитель" (producer-consumer).*
- **Взаимное исключение**: операционная система должна гарантировать, что ресурс используется только одним процессом в данный момент времени (например, два процесса не могут одновременно обращаться к одной ячейке памяти).
@@ -109,17 +109,17 @@
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_05.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_05.jpg)
*Рис. 5. Пример программы с синхронной связью.
*Рис. 5. Пример программы с синхронной связью.*
Метка `loop` указывает на последовательность инструкций xxxᵢ, которые генерируют данные `с`. После этого производитель оправляет эти данные для потребителя и потом возвращается к началу цикла и так далее. В свою очередь потребитель получает данные (receive) от производителя, выполняет над ними нужные операции и снова возвращается к началу цикла.
Метка `loop` указывает на последовательность инструкций `xxxᵢ`, которые генерируют данные `с`. После этого производитель оправляет эти данные для потребителя и потом возвращается к началу цикла и так далее. В свою очередь потребитель получает данные (receive) от производителя, выполняет над ними нужные операции и снова возвращается к началу цикла.
**Приоритет очерёдности** `a``b`,`a` предшествует `b`:
- Потребитель не может использовать данные до их получения (событие sendᵢ должно происходить раньше или в тот же момент времени, когда происходит `rcvᵢ` (получение) этих данных);
- Потребитель не может использовать данные до их получения (событие `sendᵢ` должно происходить раньше или в тот же момент времени, когда происходит `rcvᵢ` (получение) этих данных);
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_06.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_06.jpg)
*Рис. 6. Пример программы с синхронной связью c учётом приоритета очерёдности.
*Рис. 6. Пример программы с синхронной связью c учётом приоритета очерёдности.*
- Производитель не может перезаписать данные до их использования потребителем (получение данных должно происходить раньше, чем их перезапишет следующая `i+1` посылка).
@@ -127,7 +127,7 @@
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_07.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_07.jpg)
*Рис. 7. Пример буфера FIFO без ограничений приоритета.
*Рис. 7. Пример буфера FIFO без ограничений приоритета.*
Буфер FIFO ослабляет ограничения, связанные с синхронизацией. Производитель может опередить потребителя на `N` значений (где N — глубина данного буфера).
@@ -137,7 +137,7 @@
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_08.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_08.jpg)
*Рис. 8. Пример кольцевого буфера без ограничений приоритета с указателями на начало и конец очереди.
*Рис. 8. Пример кольцевого буфера без ограничений приоритета с указателями на начало и конец очереди.*
У нас есть буфер на 3 элемента (очередь) и два указателя: один указывает на место, куда мы будем писать (`write_ptr`), а другой указывает на место, откуда мы будем читать (`read_ptr`). В очередной момент времени происходит генерация новых данных (`send c₀`) — они записываются в место, куда указывает `write_ptr`. После этого данный указатель сдвигается на одну ячейку вправо (`i+1`). Далее мы снимаем данные с первой ячейки (`rcv()`) c₀ и указатель `read_ptr` сдвигается на следующую ячейку (`c₁`) и так далее.
@@ -145,7 +145,7 @@
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_09.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_09.jpg)
*Рис. 9. Пример программы буфера FIFO с общей памятью без ограничений приоритета.
*Рис. 9. Пример программы буфера FIFO с общей памятью без ограничений приоритета.*
Данный буфер **не применяет никаких ограничений приоритета** (*например, `rcv()` может быть вызван до любой отправки*) и поэтому работает неправильно. Чтобы устранить эту проблему, нам поможет концепция *семафоров*.
@@ -172,7 +172,7 @@ Semaphore — это тип данных, число ≥ 0.
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_10.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_10.jpg)
*Рис. 10. Потоки `А` и `B` .
*Рис. 10. Потоки `А` и `B` .*
Решение:
@@ -182,7 +182,7 @@ Semaphore — это тип данных, число ≥ 0.
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_11.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_11.jpg)
*Рис. 11. Потоки `A` и `B` с семафорами для приоритета.
*Рис. 11. Потоки `A` и `B` с семафорами для приоритета.*
Если мы в потоке B придём раньше до `B₄`, то `s` по умолчанию = 0 и мы застрянем на инструкции `wait(s)`. В это время первый поток А доходит до `signal(s)`, то есть увеличивает `s` на 1, соответственно внутри `wait` `s` тоже увеличилось на 1. Мы прошли этот `wait` и семафор снова стал нулём.Таким образом, мы получили синхронизацию, которую хотели.
@@ -208,16 +208,16 @@ Semaphore — это тип данных, число ≥ 0.
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_12.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_12.jpg)
*Рис. 12. Пример программы буфера FIFO с семафорами.
*Рис. 12. Пример программы буфера FIFO с семафорами.*
- выполняется приоритет, управляемый семафором `sendᵢ` `revᵢ`;
- выполняется приоритет, управляемый семафором `sendᵢ` `rcvᵢ`;
- здесь есть один ресурс, управляемый семафором: количество символов в буфере;
- всё ещё некорректная ситуация, так как производитель может переполнить буфер;
- должны применять требование `rcvᵢ` `sendᵢ₊₁>`.
- должны применять требование `rcvᵢ` `sendᵢ₊₁`.
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_13.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_13.jpg)
*Рис. 13. Пример программы буфера FIFO с семафорами с применением требования `rcvᵢ``sendᵢ₊₁.`
*Рис. 13. Пример программы буфера FIFO с семафорами с применением требования `rcvᵢ` ≤ `sendᵢ₊₁.`*
Ресурсы, управляемые семафорами: символы в FIFO, свободное место в FIFO.
Работает с одним производителем и потребителем.
@@ -228,7 +228,7 @@ Semaphore — это тип данных, число ≥ 0.
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_14.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_14.jpg)
*Рис. 14. Код к конкретной задаче.
*Рис. 14. Код к конкретной задаче.*
Результат: у вас есть 200 рублей и баланс счёта уменьшился на 200 рублей.
@@ -236,7 +236,7 @@ Semaphore — это тип данных, число ≥ 0.
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_15.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_15.jpg)
*Рис. 15. Перекрытие потоков.
*Рис. 15. Перекрытие потоков.*
Результат: у вас есть 200 рублей, а баланс счёта уменьшился на 100 рублей.
@@ -244,13 +244,13 @@ Semaphore — это тип данных, число ≥ 0.
Для некоторых сегментов кода, называемых критическими секциями (**critical sections**) мы хотели бы убедиться, что никакие два выполнения не перекрываются.
Это ограничение называется взаимным исключением (**mutual exclusion**).
**Решение**: внедрить в критические секции обёртки, которые гарантируют **атомарность**, то есть делают их похожими но отдельные мгновенные операции.
**Решение**: внедрить в критические секции обёртки, которые гарантируют **атомарность**, то есть делают их похожими на отдельные мгновенные операции.
### Семафоры для взаимных исключений
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_16.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_16.jpg)
*Рис. 16. Функция из предыдущего примера.
*Рис. 16. Функция из предыдущего примера.*
Нам нужно гарантировать, что двойной вызов функции `debit` не пересекается. То есть либо `a` предшествует `b`, либо `b` предшествует `a` (они не пересекаются!).
@@ -262,7 +262,7 @@ Semaphore — это тип данных, число ≥ 0.
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_17.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_17.jpg)
*Рис. 17. Итоговая функция с семафором для взаимных исключений.
*Рис. 17. Итоговая функция с семафором для взаимных исключений.*
### Проблемы атомарности
@@ -271,13 +271,13 @@ Semaphore — это тип данных, число ≥ 0.
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_18.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_18.jpg)
*Рис. 18. Потоки производители для нашего примера.
*Рис. 18. Потоки производители для нашего примера.*
Справиться с этим помогут наши блокировки:
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_19.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_19.jpg)
*Рис. 19. Программа буфера FIFO с блокировками.
*Рис. 19. Программа буфера FIFO с блокировками.*
### Мощность семафора
@@ -293,7 +293,7 @@ Semaphore — это тип данных, число ≥ 0.
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_20.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_20.jpg)
*Рис. 20. Итоговая программа буфера FIFO с блокировками для защиты переменных `in` и `out`.
*Рис. 20. Итоговая программа буфера FIFO с блокировками для защиты переменных `in` и `out`.*
### Реализация семафоров
@@ -310,20 +310,21 @@ Semaphore — это тип данных, число ≥ 0.
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_21.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_21.jpg)
*Рис. 21. Пересылка одинаковой суммой денег с одного счёта на другой.
*Рис. 21. Пересылка одинаковой суммой денег с одного счёта на другой.*
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_22.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_22.jpg)
*Рис. 22. Функция пересылки денег.
*Рис. 22. Функция пересылки денег.*
Что же может пойти не так?
Thread 1: wait (lock [0903]); (поток 1 блокирует 0903)
Thread 2: wait (lock [1103]); (поток 2 параллельно блокирует 1103)
Thread 1: wait (lock [1103]); //не завершиться, пока не произойдёт signal 2 потока (заблокирован, потому что предыдущий поток его уже заблокировал, кончился ресурс)
Thread 1: wait (lock [0903]); //не завершиться, пока не произойдёт signal 1 потока.
Thread 2: wait (lock [0903]); //не завершиться, пока не произойдёт signal 1 потока.
Ни один поток не может добиться прогресса - это называется **Тупик** или **Deadlock**.
**Deadlock** ситуация, при которой несколько процессов находятся в состоянии ожидания ресурсов, занятых друг другом, и ни один из них не может продолжать свое выполнение.
@@ -332,9 +333,9 @@ Thread 1: wait (lock [0903]); //не завершиться, пока не пр
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_23.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_23.jpg)
*Рис. 23. Карикатура обедающих философов за столом.
*Рис. 23. Карикатура обедающих философов за столом.*
Философы мыслят глубокими мыслями, но имеют простые мирские потребности. Когда вы голодны, группа из `N` философов будет сидеть вокруг стола с N палочками для еды, разбросанными между ними. Еда подаётся, и каждый философ наслаждается неторопливой едой, используя палочки для еды с обеих сторон.
Философы мыслят глубокими мыслями, но имеют простые мирские потребности. Когда вы голодны, группа из `N` философов будет сидеть вокруг стола с `N` палочками для еды, разбросанными между ними. Еда подаётся, и каждый философ наслаждается неторопливой едой, используя палочки для еды с обеих сторон.
Они очень вежливы и терпеливы, и каждый соблюдает обеденный протокол.
Алгоритмы философа:
@@ -364,7 +365,7 @@ Thread 1: wait (lock [0903]); //не завершиться, пока не пр
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_24.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_24.jpg)
*Рис. 24. Решение проблемы обедающих философов.
*Рис. 24. Решение проблемы обедающих философов.*
Доказательство: `Deadlock` означает, что каждый философ ждёт ресурса, которым владеет какой-то другой философ. Но философ, держащий самую большую палочку для еды не может ждать какого-либо другого философа.
@@ -372,13 +373,13 @@ Thread 1: wait (lock [0903]); //не завершиться, пока не пр
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_25.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_25.jpg)
*Рис. 25. Исправленный метод передачи денежной суммы.
*Рис. 25. Исправленный метод передачи денежной суммы.*
## Многоядерность
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_26.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_26.jpg)
*Рис. 26. Многоядерность.
*Рис. 26. Многоядерность.*
1. Современные процессоры обычно имеют от 2 до 8 ядер, где каждое ядро имеет собственный кэш для повышения производительности.
2. Ядро могут использоваться совместно для ускорения работы приложения.
@@ -392,7 +393,7 @@ Thread 1: wait (lock [0903]); //не завершиться, пока не пр
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_27.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_27.jpg)
*Рис. 27. Проблема многоядерности.
*Рис. 27. Проблема многоядерности.*
1) Ядро 0 загружает данные из памяти по адресу `A` число два.
2) Ядро 2 выгружает в память по адресу `A` число три.
@@ -418,7 +419,7 @@ Thread 1: wait (lock [0903]); //не завершиться, пока не пр
Протоколы когерентности должны обеспечивать соблюдение двух правил:
- распространяющаяся запись (**Write propagation**): записи в конечном итоге становятся видимыми для всех процессоров (если кто-то из процессоров пишет куда-то, то нужно однозначно остальным об этом сообщить);
сериализация записи (**Write serialization**): записи в одно и то же место сериализуются (все процессоры видят их в том же порядке).
- сериализация записи (**Write serialization**): записи в одно и то же место сериализуются (все процессоры видят их в том же порядке).
Как обеспечить распространение записи:
@@ -436,7 +437,7 @@ Thread 1: wait (lock [0903]); //не завершиться, пока не пр
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_28.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_28.jpg)
*Рис. 28. Процессоры со `Snoopy Cache`, которые подключены к основной памяти.
*Рис. 28. Процессоры со `Snoopy Cache`, которые подключены к основной памяти.*
То есть каждый раз, когда процессор обращается к кэш памяти, он выставляет информацию на общую шину. И все кэши видят когда кто-то на эту шину выставляет информацию.
@@ -452,7 +453,7 @@ Snoopy кэш отличается от обычного кэша наличие
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_29.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_29.jpg)
*Рис. 29. Упрощенная форма `Snoopy Cache`.
*Рис. 29. Упрощенная форма `Snoopy Cache`.*
**Snoopy протокол (FSM)** это конечный автомат, который зависит от того что происходит на шине и обновляет значения состояния.
@@ -465,14 +466,14 @@ Snoopy кэш отличается от обычного кэша наличие
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_30.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_30.jpg)
*Рис. 30. Протокол `VI`.
*Рис. 30. Протокол `VI`.*
Когда мы находимся в состоянии `Invalid`, и какое-то ядро запрашивает данные, то происходит `Processor Read` (PrRd). Затем он получает данные в свой кэш и выставляет эти данные как `Valid`.
В какой-то момент это ядро видит, что какое-то ядро записало по этому адресу (то есть на шине произошла запись `Bus Write`), тогда оно сразу меняет состояние этой ячейки на `Invalid`, потому что в этот момент времени у него неактуальные данные.
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_31.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_31.jpg)
*Рис. 31. Основные действия для данного протокола.
*Рис. 31. Основные действия для данного протокола.*
Таким образом, если мы читаем данные, то мы переходим в состояние `Valid`.Если мы видим, что какое-то ядро записывает по этому адресу, то переходим в состояние `Invalid`.
@@ -480,17 +481,17 @@ Snoopy кэш отличается от обычного кэша наличие
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_32.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_32.jpg)
*Рис. 32. Пример применения протокола `Valid/Invalid`.
*Рис. 32. Пример применения протокола `Valid/Invalid`.*
1) Допустим, ядро 0 сначала загружаю по адресу `A`. На шине запрашивается чтение, в кэш попадает запись с состоянием `Valid`.
2) Затем загружается второе ядро по адресу `A`, теперь там тоже запись `Valid`.
3) Теперь происходит запись числа в память, кэш видит это и делает `Invalidate` данных (обнуляет их).
4) Когда произойдёт очередной `load`, он увидит, что мы находимся в состоянии `Invalidate`.
5) Теперь просто зачитаем обновленные данные.
1) Допустим, ядро 0 сначала загружает по адресу `A` число 2. На шине запрашивается чтение, в кэш попадает запись с состоянием `Valid`.
2) Затем загружает ядро 1 по адресу `A` число 2, теперь там тоже запись `Valid`.
3) Теперь происходит запись числа 3 в память через ядро 0, кэш ядра 1 видит это и делает `Invalidate` данных (обнуляет их).
4) Когда произойдёт очередной `load` на ядре 1, он увидит, что данные находятся в состоянии `Invalidate`.
5) Теперь просто зачитаем обновленные данные из основной памяти.
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_33.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_33.jpg)
*Рис. 33. Пример применения протокола `Valid/Invalid` с пояснениями.
*Рис. 33. Пример применения протокола `Valid/Invalid` с пояснениями.*
Проблемы `VI`:
@@ -501,9 +502,9 @@ Snoopy кэш отличается от обычного кэша наличие
Каждая строка в каждом кэше поддерживает `MSI` состояния:
- `I`-кэш не содержит адреса;
- `S`-кэш содержит адрес, но он так же может находится в других кэшах, следовательно он может быть только прочитан;
- `M`-кэш содержит этот адрес, следовательно он может быть и прочитан и записан — любой другой кэш имевший этот адрес будет признан недействительным (то есть как только запишется по этому адресу все остальные аннулируют информацию об этом).
- `I`- кэш не содержит адреса;
- `S`- кэш содержит адрес, но он так же может находится в других кэшах, следовательно он может быть только прочитан;
- `M`- только этот кэш содержит этот адрес, следовательно он может быть и прочитан и записан любой другой кэш, имевший этот адрес, будет признан недействительным (то есть как только запишется по этому адресу, все остальные аннулируют информацию об этом).
### MSI протокол FSM
@@ -515,22 +516,22 @@ Snoopy кэш отличается от обычного кэша наличие
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_34.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_34.jpg)
*Рис. 34. `MSI` протокол.
*Рис. 34. `MSI` протокол.*
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_35.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_35.jpg)
*Рис. 35. Основные действия для данного протокола.
*Рис. 35. Основные действия для данного протокола.*
- Недостатки `VI`: каждая запись обновляет основную память, и каждая запись требует широковещательной передачи и слежки.
- `MSI`: возможность реализации кэша с обратной записью (`writeback`) + удовлетворяет локальную запись.
### Оптимизация MSI: состояние E
Наблюдение: выполнение последовательной чтения-изменения-записи на частных данных является обычным делом.
Наблюдение: выполнение последовательностей чтения-изменения-записи на частных данных является обычным делом.
В чём проблема `MSI`?
- Две данные транзакции для каждого чтения-изменения-записи частных данных.
- Две шинные транзакции для каждого чтения-изменения-записи частных данных.
Решение: `Е-состояние` (`Exclusive`)
@@ -548,7 +549,7 @@ Snoopy кэш отличается от обычного кэша наличие
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_36.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_36.jpg)
*Рис. 36. Протокол `MESI`: усовершенствованный.
*Рис. 36. Протокол `MESI`: усовершенствованный.*
### Когерентность кэш и ложное совместное использование
@@ -556,15 +557,19 @@ Snoopy кэш отличается от обычного кэша наличие
![../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_37.jpg](../.pic/Lectures/18.%20Synchronization.%20Cache%20coherence/fig_37.jpg)
*Рис. 37. Строка кэша.
*Рис. 37. Строка кэша.*
Предположим `P₁` записывает `wordᵢ` и `P₂` записывает `wordₖ` и оба слова имеют один и тот же адрес строки.
Что может произойти?
Из-за того что присутствуют алгоритмы когерентности, будет происходить *пинг-понг*.
Из-за того, что присутствуют алгоритмы когерентности, будет происходить *пинг-понг*.
Строка может быть недействительной (*пинг-понг*) много раз без необходимости, потому что адреса находятся в одной строке.
### Основные материалы лекции
## Основные материалы лекции
1. [Ссылка](https://www.youtube.com/watch?v=wr7KuOSPP5I&list=PL0def37HEo5KHPjwK7A5bd4RJGg4djPVf&index=26) на видеозапись лекции
2. [Ссылка](https://onedrive.live.com/?authkey=!AIXUSz0MyutL6hs&id=1FF28DEC684C2C56!81692&cid=1FF28DEC684C2C56) на лекцию в формате Power Point
## Дополнительные материалы к лекции для саморазвития
1. [Демонстрация протокола MESI](https://www.scss.tcd.ie/jeremy.jones/vivio/caches/MESIHelp.htm)