О Подсистема памяти
Одна из самых больших проблем любого процессора — обеспечение его загрузки. За последние несколько лет производительность процессоров необычайно выросла, в среднем удваиваясь каждые два года. Производительность памяти и ввода-вывода не успевает за этими темпами.
В 1991 году я купил новую IBM PC для домашних нужд. В ней был установлен процессор Intel 386 20 МГц, 70-наносекундная память и жесткий диск с временем доступа 16 миллисекунд. Маломощный процессор 386 не долго меня устраивал; поэтому я, как и многие другие, начал бесконечную гонку за новейшей аппаратурой, приобретая последовательно системы с процессорами 486 и Pentium. В последнем купленном мною компьютере (который уже тоже устарел) установлены процессоры Pentium Pro 200 МГц, 60-наносекундная память и жесткие диски со временем доступа 8,5 миллисекунд.
Да, за последние несколько лет разрыв в скорости между процессором и памятью-вводом/выводом вырос невероятно. Теперь вполне возможна ситуация, когда память и ввод-вывод не смогут поставлять достаточно информации для поддержания загрузки процессора, и последний будет проводить множество своих высокоскоростных циклов в ожидании выборки команд или данных.
Универсальный прием для компенсации разницы в производительности между процессором и основной памятью — применение кэшей. Как мы уже говорили, кэш — это быстродействующая память, используемая для хранения блоков команд и данных, к которым процессор недавно обращался. При этом предполагается, что в ближайшем будущем процессор будет обращаться к тем же самым блокам.
Кэши эффективны благодаря тому, что большинство программ обладают так называемыми пространственной и временной локализацией. Это означает, что программа, скорее всего, обратится к команде или элементу данных, расположенным в памяти недалеко от места последнего обращения (пространственная локализация); а также что такой доступ произойдет через короткий отрезок времени (временная локализация). Нетрудно предположить, некоторые программы обладают большей степенью локализации, чем другие. Программа, предполагающая выполнение многих циклов или большой объем повторной обработки одних и тех же данных, имеет очень высокую степень локализации. Приложения для коммерческих расчетов, наоборот, выполняют мало обработки такого сорта, и имеют несколько меньшую степень локализации. Большие кэши и иерархия кэшей могут обеспечить загрузку процессора данными и командами даже при низких уровнях локализации.
При использовании иерархии кэшей происходит следующее: если нужная процессору информация отсутствует в кэше L1, процессор обращается к кэшу L2. Если информация не найдена и там, то происходит обращение к основной памяти. Пока идет поиск информации и выборка ее в регистр, процессор простаивает. Обычно это называют циклами простоя (stall cycles) процессора. В том случае, если информации нет даже в основной памяти и система должна обратиться к диску, процессор не ждет, а переключается на выполнение другой задачи в системе. Такую ситуацию обычно называют страничной ошибкой (page fault). Подробней мы поговорим об этом в главе 8.
Высокая производительность Muskie достигается с помощью небольшого 8-кило-байтного кэша команд L1 и 256-килобайтного кэша данных L1. Большой кэш данных реализован на четырех отдельных 64-килобайтных микросхемах памяти высокого быстродействия. Будучи однокристальными процессорами, Cobra и Apache имеют гораздо меньшие внутренние кэши L1 (4К и 8К для команд и данных соответственно). Эти внутренние кэши дополняются кэшами L2 большего размера, выполненными в виде отдельных микросхем. Часть производительности Apache достигается за счет очень больших кэшей L2 объемом от 4 до 8 мегабайт.
Несмотря на использование больших кэшей и иерархии кэшей, большинство процессоров все равно тратят много циклов простоя, ожидая выборки из памяти. Проблема заключается в шине между процессором и основной памятью. Большая часть систем, включая ранние AS/400, имеют одну такую шину, обычно высокоскоростную, но все равно работающую медленнее самого процессора. Например, мой Intel Pentium Pro 200 МГц работает с шиной памяти 66 МГц. Это означает, что при обращении к памяти процессор простаивает по три цикла на каждый цикл шины. Легко понять, что таких циклов простоя может быть много.
В конфигурации SMP ситуация может значительно ухудшиться. Теперь одну шину памяти и одну основную память пытаются задействовать несколько процессоров. Так как в данный момент времени шина может использоваться только одним процессором, то все остальные процессоры, которым она понадобилась в этот момент, обречены ждать. А если та же шина памяти используется еще и для ввода-вывода, положение еще более усугубляется.
Эта борьба за шину памяти приводит к уменьшению производительности при добавлении к системе SMP каждого нового процессора. Например, добавление второго процессора не позволит увеличить общую производительность на 100 процентов; фактическое увеличение будет несколько меньшим из-за борьбы за память. Добавление третьего и четвертого процессора еще сильнее сократит прирост производительности на один процессор. А когда дело дойдет до восьми и более процессоров, рост производительности системы SMP может и вовсе прекратиться.