Конфликты по данным
Конфликты по данным возникают, когда несколько последовательно выполняемых команд оказываются логически зависимыми друг от друга. Если порядок обращения к данным при конвейерной обработке некоторой последовательности взаимосвязанных команд будет отличаться от порядка обращения к данным в неконвейерной машине, говорят о конфликте по данным. Рассмотрим конвейерное выполнение следующей последовательности команд:
ADD R1,R2,R3 ; в регистр R1 помещается сумма R2 и R3
SUB R4,R2,R1 ; регистр R4 равен разности R1 и R2
MUL R5,R1,R6 ; регистр R5 равен разности R1 и R6 .
В приведенной последовательности команды вычитания и умножения используют результат выполнения команды сложения. Рассмотрим процесс выполнения этих команд в конвейерной системе (см. рис. 28). Команда сложения сформирует результат в конце такта выполнения (EX в такте 4) и в такте записи (WR, такт 5) поместит его в регистр процессора. После этого новое значение станет доступным для считывания. Команде вычитания потребуется обратиться за операндом в такте RD (такт 4), однако в это время регистр
№ такта | |||||||||
ADD R1,R2,R3 | IF | ID | RD | EX | WR | ||||
ëданные записаны | |||||||||
SUB R4,R2,R1 | IF | ID | RD | EX | WR | ||||
Данные считываются ì | |||||||||
MUL R5,R1,R6 | IF | ID | RD | EX | WR |
а)
№ такта | |||||||||
ADD R1,R2,R3 | IF | ID | RD | EX | WR | ||||
SUB R4,R2,R1 | IF | ID | * | * | RD | EX | WR | ||
MUL R5,R1,R6 | IF | * | * | ID | RD | EX | WR |
б)
№ такта | |||||||||
ADD R1,R2,R3 | IF | ID | RD | EX | WR | ||||
Момент пересылки данных ì | |||||||||
SUB R4,R2,R1 | IF | ID | RD | EX | WR | ||||
ëданные доступны | |||||||||
MUL R5,R1,R6 | IF | ID | RD | EX | WR |
в)
Рис. 28 Конфликт по данным и его разрешение: а) операнд считывается до того, как он записан; б) задержка команды с потерей производительности; в) ускоренная пересылка данных.
будет все еще содержать некоторое неопределенной значение. Можно считать, что это старое значение, записанное некоторой предыдущей командой (см. рис. 28 а), однако это не всегда так. Если в момент выполнения команды сложения произойдет прерывание, то перед прерыванием команда будет завершена и в регистр R1 будет помещен правильный результат.
Простейшим способом борьбы с конфликтом будет задержать выполнение команды вычитания на два такта, в течение которых команда сложения «успеет» сформировать результат (см. рис. 28 б). Естественно, что такая задержка приведет к потере производительности.
Отметим, что реально данные для команды вычитания потребуются только в момент начала стадии выполнения (начало такта номер 5 на рис. 28 а). В то же время фактически результат команды сложения будет готов в конце такта выполнения команды вычитания (конец такта номер 4 на рис. 28 а). Конфликта по данным можно избежать, если результат выполнения команды сложения не помещать в регистр для последующего считывания, а переслать непосредственно на вход исполнительного устройства перед началом такта выполнения команды вычитания (см. рис. 28 в). Подобный прием называется ускоренной пересылкой данных.
Однако не все конфликты по данным можно преодолеть, используя механизм ускоренной пересылки. Рассмотрим выполнение простого оператора A = B + C на языке высокого уровня. Скорее всего, компилятор сформирует для такого оператора приблизительно следующую последовательность команд:
LOAD R1, B ;загрузка из памяти значения B
LOAD R2, C ;загрузка из памяти значения C
ADD R3, R1, R2 ;суммирование
STORE A, R3 ; сохранение результата.
Как уже отмечалось, обращение к памяти является достаточно длительной операцией, поэтому между командой загрузки операнда C и командой сложения возникает конфликт по данным, который можно преодолеть, только если задержать выполнение команды сложения до окончания выполнения команды загрузки. То же самое можно сказать и о команде записи в память, которая следует после сложения. Тут так же имеет место конфликт, так как несформированное и не записанное в регистр значение невозможно записать в память. Как видим, в данном конкретном примере невозможно избежать конфликтов, если не задержать выполнение отдельных команд. Пусть команда обращения к памяти требует для выполнения два такта. Тогда, очевидно, необходимо задержать на два такта команду сложения и еще на один такт команду записи в память.
Избежать потери производительности можно только если изменить порядок выполнения команд с учетом других выполняемых команд. Пусть, например, в программе выполняются два последовательных оператора A = B + C и E = D + F. Последовательность команд для решения задачи будет следующей.
LOAD R1, B ;загрузка из памяти значения B
LOAD R2, C ;загрузка из памяти значения C
ADD R3, R1, R2 ;суммирование
STORE A, R3 ; сохранение результата A.
LOAD R1, D ;загрузка из памяти значения D
LOAD R2, F ;загрузка из памяти значения F
ADD R3, R1, R2 ;суммирование
STORE E, R3 ; сохранение результата E.
Можно избежать задержек, если изменить порядок выполнения команд в данной последовательности следующим образом:
LOAD R1,B ;загрузка из памяти значения B
LOAD R2,C ;загрузка из памяти значения C
LOAD R1,D ;загрузка из памяти значения D
ADD R3,R1,R2 ;суммирование
LOAD R2,F ;загрузка из памяти значения F
STORE A,R3 ; сохранение результата A.
ADD R3,R1,R2 ;суммирование
STORE E,R3 ; сохранение результата E.
Отметим, что таким образом удается избежать почти всех задержек, за исключением задержки перед выполнением последней команды сохранения. Подобное переупорядочение команд можно выполнить, если заранее выявить в последовательности команд зависимости по данным. Эта задача может решаться на уровне компиляторов с языков высокого уровня. Для этого необходимо рассмотреть непрерывную последовательность команд, внутри которой нет команд условного перехода. Если начала выполняться первая команда последовательности, то и все остальные обязательно будут выполнены. Тогда можно построить граф зависимости команд друг от друга и переупорядочить команды внутри последовательности для компенсации задержек.
Существуют аппаратные методы, позволяющие изменить порядок выполнения команд в случае возникновения конфликта. Эти методы получили общее название методов внеочередного выполнения или методов динамической оптимизации. При этом команды, задержанные вследствие конфликта и ожидающие появления данных, накапливаются в специальном буфере, а логически не связанные с ними команды подаются на выполнение в обход буфера. Отметим, что в случае, когда процессор может динамически изменить порядок выполнения команд, порядок появления результатов на выходе процессора будет отличаться от порядка, заданного программой. Поэтому возникает необходимость наличия выходного блока, который фиксирует исходный порядок команд и обеспечивает соответствие между порядком команд и порядком появления результатов на выходе процессора.
Еще одним аппаратным методом минимизации конфликтов по данным является метод переименования регистров (register renaming). Он получил свое название от широко применяющегося в компиляторах метода переименования - метода размещения данных, способствующего сокращению числа зависимостей и тем самым увеличению производительности при отображении необходимых исходной программе объектов (например, переменных) на аппаратные ресурсы (например, ячейки памяти и регистры).
При аппаратной реализации метода переименования регистров выделяются логические регистры, обращение к которым выполняется с помощью соответствующих полей команды, и физические регистры, которые размещаются в аппаратном регистровом файле процессора. Номера логических регистров динамически отображаются на номера физических регистров посредством таблиц отображения, которые обновляются после декодирования каждой команды. Каждый новый результат записывается в новый физический регистр. Однако предыдущее значение каждого логического регистра сохраняется и может быть восстановлено в случае, если выполнение команды должно быть прервано из-за возникновения исключительной ситуации или неправильного предсказания направления условного перехода.
В процессе выполнения программы генерируется множество временных регистровых результатов. Эти временные значения записываются в регистровые файлы вместе с постоянными значениями. Временное значение становится новым постоянным значением, когда завершается выполнение команды (фиксируется ее результат). В свою очередь, завершение выполнения команды происходит, когда все предыдущие команды успешно завершились в заданном программой порядке.
Программист имеет дело только с логическими регистрами. Реализация физических регистров от него скрыта. Как уже отмечалось, номера логических регистров ставятся в соответствие номерам физических регистров. Отображение реализуется с помощью таблиц отображения, которые обновляются после декодирования каждой команды. Каждый новый результат записывается в физический регистр. Однако до тех пор, пока не завершится выполнение соответствующей команды, значение в этом физическом регистре рассматривается как временное.
Метод переименования регистров упрощает контроль зависимостей по данным. В машине, которая может выполнять команды не в порядке их расположения в программе, номера логических регистров могут стать двусмысленными, поскольку один и тот же регистр может быть назначен последовательно для хранения различных значений. Но поскольку номера физических регистров уникально идентифицируют каждый результат, все неоднозначности устраняются.
Дата добавления: 2021-02-19; просмотров: 326;